2 ==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
10 http://www.apache.org/licenses/LICENSE-2.0
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 ==================================================================================
30 "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
31 rtmgrclient "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client"
32 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/models"
33 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
34 httptransport "github.com/go-openapi/runtime/client"
35 "github.com/go-openapi/strfmt"
36 "github.com/gorilla/mux"
37 "github.com/segmentio/ksuid"
38 "github.com/spf13/viper"
41 //-----------------------------------------------------------------------------
43 //-----------------------------------------------------------------------------
45 func idstring(err error, entries ...fmt.Stringer) string {
46 var retval string = ""
47 var filler string = ""
48 for _, entry := range entries {
50 retval += filler + entry.String()
53 retval += filler + "(NIL)"
57 retval += filler + "err(" + err.Error() + ")"
63 //-----------------------------------------------------------------------------
65 //-----------------------------------------------------------------------------
67 var e2tSubReqTimeout time.Duration
68 var e2tSubDelReqTime time.Duration
69 var e2tRecvMsgTimeout time.Duration
70 var waitRouteCleanup_ms time.Duration
71 var e2tMaxSubReqTryCount uint64 // Initial try + retry
72 var e2tMaxSubDelReqTryCount uint64 // Initial try + retry
73 var readSubsFromDb string
74 var restDuplicateCtrl duplicateCtrl
82 restSubsDb Sdlnterface
85 Counters map[string]xapp.Counter
95 type SubmgrRestartTestEvent struct{}
96 type SubmgrRestartUpEvent struct{}
99 xapp.Logger.Info("SUBMGR")
101 viper.SetEnvPrefix("submgr")
102 viper.AllowEmptyEnv(true)
105 func NewControl() *Control {
107 transport := httptransport.New(viper.GetString("rtmgr.HostAddr")+":"+viper.GetString("rtmgr.port"), viper.GetString("rtmgr.baseUrl"), []string{"http"})
108 rtmgrClient := RtmgrClient{rtClient: rtmgrclient.New(transport, strfmt.Default)}
110 registry := new(Registry)
111 registry.Initialize()
112 registry.rtmgrClient = &rtmgrClient
114 tracker := new(Tracker)
117 c := &Control{e2ap: new(E2ap),
120 e2SubsDb: CreateSdl(),
121 restSubsDb: CreateRESTSdl(),
122 Counters: xapp.Metric.RegisterCounterGroup(GetMetricsOpts(), "SUBMGR"),
125 c.ReadConfigParameters("")
127 // Register REST handler for testing support
128 xapp.Resource.InjectRoute("/ric/v1/test/{testId}", c.TestRestHandler, "POST")
129 xapp.Resource.InjectRoute("/ric/v1/symptomdata", c.SymptomDataHandler, "GET")
131 go xapp.Subscription.Listen(c.SubscriptionHandler, c.QueryHandler, c.SubscriptionDeleteHandlerCB)
133 if readSubsFromDb == "false" {
137 restDuplicateCtrl.Init()
139 // Read subscriptions from db
140 xapp.Logger.Info("Reading subscriptions from db")
141 subIds, register, err := c.ReadAllSubscriptionsFromSdl()
143 xapp.Logger.Error("%v", err)
145 c.registry.subIds = subIds
146 c.registry.register = register
147 c.HandleUncompletedSubscriptions(register)
150 restSubscriptions, err := c.ReadAllRESTSubscriptionsFromSdl()
152 xapp.Logger.Error("%v", err)
154 c.registry.restSubscriptions = restSubscriptions
159 func (c *Control) SymptomDataHandler(w http.ResponseWriter, r *http.Request) {
160 subscriptions, _ := c.registry.QueryHandler()
161 xapp.Resource.SendSymptomDataJson(w, r, subscriptions, "platform/subscriptions.json")
164 //-------------------------------------------------------------------
166 //-------------------------------------------------------------------
167 func (c *Control) ReadConfigParameters(f string) {
169 // viper.GetDuration returns nanoseconds
170 e2tSubReqTimeout = viper.GetDuration("controls.e2tSubReqTimeout_ms") * 1000000
171 if e2tSubReqTimeout == 0 {
172 e2tSubReqTimeout = 2000 * 1000000
174 xapp.Logger.Info("e2tSubReqTimeout %v", e2tSubReqTimeout)
175 e2tSubDelReqTime = viper.GetDuration("controls.e2tSubDelReqTime_ms") * 1000000
176 if e2tSubDelReqTime == 0 {
177 e2tSubDelReqTime = 2000 * 1000000
179 xapp.Logger.Info("e2tSubDelReqTime %v", e2tSubDelReqTime)
180 e2tRecvMsgTimeout = viper.GetDuration("controls.e2tRecvMsgTimeout_ms") * 1000000
181 if e2tRecvMsgTimeout == 0 {
182 e2tRecvMsgTimeout = 2000 * 1000000
184 xapp.Logger.Info("e2tRecvMsgTimeout %v", e2tRecvMsgTimeout)
186 // Internal cfg parameter, used to define a wait time for RMR route clean-up. None default
187 // value 100ms used currently only in unittests.
188 waitRouteCleanup_ms = viper.GetDuration("controls.waitRouteCleanup_ms") * 1000000
189 if waitRouteCleanup_ms == 0 {
190 waitRouteCleanup_ms = 5000 * 1000000
192 xapp.Logger.Info("waitRouteCleanup %v", waitRouteCleanup_ms)
194 e2tMaxSubReqTryCount = viper.GetUint64("controls.e2tMaxSubReqTryCount")
195 if e2tMaxSubReqTryCount == 0 {
196 e2tMaxSubReqTryCount = 1
198 xapp.Logger.Info("e2tMaxSubReqTryCount %v", e2tMaxSubReqTryCount)
200 e2tMaxSubDelReqTryCount = viper.GetUint64("controls.e2tMaxSubDelReqTryCount")
201 if e2tMaxSubDelReqTryCount == 0 {
202 e2tMaxSubDelReqTryCount = 1
204 xapp.Logger.Info("e2tMaxSubDelReqTryCount %v", e2tMaxSubDelReqTryCount)
206 readSubsFromDb = viper.GetString("controls.readSubsFromDb")
207 if readSubsFromDb == "" {
208 readSubsFromDb = "true"
210 xapp.Logger.Info("readSubsFromDb %v", readSubsFromDb)
211 c.LoggerLevel = viper.GetUint32("logger.level")
212 if c.LoggerLevel == 0 {
217 //-------------------------------------------------------------------
219 //-------------------------------------------------------------------
220 func (c *Control) HandleUncompletedSubscriptions(register map[uint32]*Subscription) {
222 xapp.Logger.Debug("HandleUncompletedSubscriptions. len(register) = %v", len(register))
223 for subId, subs := range register {
224 if subs.SubRespRcvd == false {
225 subs.NoRespToXapp = true
226 xapp.Logger.Debug("SendSubscriptionDeleteReq. subId = %v", subId)
227 c.SendSubscriptionDeleteReq(subs)
232 func (c *Control) ReadyCB(data interface{}) {
233 if c.RMRClient == nil {
234 c.RMRClient = xapp.Rmr
238 func (c *Control) Run() {
239 xapp.SetReadyCB(c.ReadyCB, nil)
240 xapp.AddConfigChangeListener(c.ReadConfigParameters)
244 //-------------------------------------------------------------------
246 //-------------------------------------------------------------------
247 func (c *Control) GetOrCreateRestSubscription(p *models.SubscriptionParams, md5sum string, xAppRmrEndpoint string) (*RESTSubscription, string, error) {
250 var restSubscription *RESTSubscription
253 prevRestSubsId, exists := restDuplicateCtrl.GetLastKnownRestSubsIdBasedOnMd5sum(md5sum)
254 if p.SubscriptionID == "" {
256 restSubscription, err = c.registry.GetRESTSubscription(prevRestSubsId, false)
257 if restSubscription != nil {
258 restSubId = prevRestSubsId
260 xapp.Logger.Info("Existing restSubId %s found by MD5sum %s for a request without subscription ID - using previous subscription", prevRestSubsId, md5sum)
262 xapp.Logger.Info("Existing restSubId %s found by MD5sum %s for a request without subscription ID - Note: %s", prevRestSubsId, md5sum, err.Error())
265 xapp.Logger.Info("None existing restSubId %s referred by MD5sum %s for a request without subscription ID - deleting cached entry", prevRestSubsId, md5sum)
266 restDuplicateCtrl.DeleteLastKnownRestSubsIdBasedOnMd5sum(md5sum)
270 if restSubscription == nil {
271 restSubId = ksuid.New().String()
272 restSubscription, err = c.registry.CreateRESTSubscription(&restSubId, &xAppRmrEndpoint, p.Meid)
274 xapp.Logger.Error("%s", err.Error())
275 c.UpdateCounter(cRestSubFailToXapp)
280 restSubId = p.SubscriptionID
282 xapp.Logger.Info("RestSubscription ID %s provided via REST request", restSubId)
284 restSubscription, err = c.registry.GetRESTSubscription(restSubId, false)
286 xapp.Logger.Error("%s", err.Error())
287 c.UpdateCounter(cRestSubFailToXapp)
292 xapp.Logger.Info("Existing restSubscription found for ID %s, new request based on md5sum", restSubId)
294 xapp.Logger.Info("Existing restSubscription found for ID %s(%s), re-transmission based on md5sum match with previous request", prevRestSubsId, restSubId)
298 return restSubscription, restSubId, nil
301 //-------------------------------------------------------------------
303 //-------------------------------------------------------------------
304 func (c *Control) SubscriptionHandler(params interface{}) (*models.SubscriptionResponse, error) {
307 c.UpdateCounter(cRestSubReqFromXapp)
309 subResp := models.SubscriptionResponse{}
310 p := params.(*models.SubscriptionParams)
312 if c.LoggerLevel > 2 {
313 c.PrintRESTSubscriptionRequest(p)
316 if p.ClientEndpoint == nil {
317 xapp.Logger.Error("ClientEndpoint == nil")
318 c.UpdateCounter(cRestSubFailToXapp)
319 return nil, fmt.Errorf("")
322 _, xAppRmrEndpoint, err := ConstructEndpointAddresses(*p.ClientEndpoint)
324 xapp.Logger.Error("%s", err.Error())
325 c.UpdateCounter(cRestSubFailToXapp)
329 md5sum, err := CalculateRequestMd5sum(params)
331 xapp.Logger.Error("Failed to generate md5sum from incoming request - %s", err.Error())
334 restSubscription, restSubId, err := c.GetOrCreateRestSubscription(p, md5sum, xAppRmrEndpoint)
336 xapp.Logger.Error("Failed to get/allocate REST subscription")
340 subResp.SubscriptionID = &restSubId
341 subReqList := e2ap.SubscriptionRequestList{}
342 err = c.e2ap.FillSubscriptionReqMsgs(params, &subReqList, restSubscription)
344 xapp.Logger.Error("%s", err.Error())
345 restDuplicateCtrl.DeleteLastKnownRestSubsIdBasedOnMd5sum(md5sum)
346 c.registry.DeleteRESTSubscription(&restSubId)
347 c.UpdateCounter(cRestSubFailToXapp)
351 duplicate := restDuplicateCtrl.IsDuplicateToOngoingTransaction(restSubId, md5sum)
353 xapp.Logger.Info("Retransmission blocker direct ACK for request of restSubsId %s restSubId MD5sum %s as retransmission", restSubId, md5sum)
354 c.UpdateCounter(cRestSubRespToXapp)
358 go c.processSubscriptionRequests(restSubscription, &subReqList, p.ClientEndpoint, p.Meid, &restSubId, xAppRmrEndpoint, md5sum)
360 c.UpdateCounter(cRestSubRespToXapp)
364 //-------------------------------------------------------------------
366 //-------------------------------------------------------------------
368 func (c *Control) processSubscriptionRequests(restSubscription *RESTSubscription, subReqList *e2ap.SubscriptionRequestList,
369 clientEndpoint *models.SubscriptionParamsClientEndpoint, meid *string, restSubId *string, xAppRmrEndpoint string, md5sum string) {
371 xapp.Logger.Info("Subscription Request count=%v ", len(subReqList.E2APSubscriptionRequests))
373 var xAppEventInstanceID int64
374 var e2EventInstanceID int64
376 defer restDuplicateCtrl.SetMd5sumFromLastOkRequest(*restSubId, md5sum)
378 for index := 0; index < len(subReqList.E2APSubscriptionRequests); index++ {
379 subReqMsg := subReqList.E2APSubscriptionRequests[index]
380 xAppEventInstanceID = (int64)(subReqMsg.RequestId.Id)
382 trans := c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(xAppRmrEndpoint), *restSubId, subReqMsg.RequestId, &xapp.RMRMeid{RanName: *meid})
384 // Send notification to xApp that prosessing of a Subscription Request has failed.
385 err := fmt.Errorf("Tracking failure")
386 c.sendUnsuccesfullResponseNotification(restSubId, restSubscription, xAppEventInstanceID, err, clientEndpoint, trans)
390 xapp.Logger.Info("Handle SubscriptionRequest index=%v, %s", index, idstring(nil, trans))
392 subRespMsg, err := c.handleSubscriptionRequest(trans, &subReqMsg, meid, *restSubId)
394 xapp.Logger.Info("Handled SubscriptionRequest index=%v, %s", index, idstring(nil, trans))
397 c.sendUnsuccesfullResponseNotification(restSubId, restSubscription, xAppEventInstanceID, err, clientEndpoint, trans)
399 e2EventInstanceID = (int64)(subRespMsg.RequestId.InstanceId)
400 restSubscription.AddMd5Sum(md5sum)
401 xapp.Logger.Info("SubscriptionRequest index=%v processed successfullyfor %s. endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v, %s",
402 index, *restSubId, clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID, idstring(nil, trans))
403 c.sendSuccesfullResponseNotification(restSubId, restSubscription, xAppEventInstanceID, e2EventInstanceID, clientEndpoint, trans)
409 //-------------------------------------------------------------------
411 //------------------------------------------------------------------
412 func (c *Control) handleSubscriptionRequest(trans *TransactionXapp, subReqMsg *e2ap.E2APSubscriptionRequest, meid *string,
413 restSubId string) (*e2ap.E2APSubscriptionResponse, error) {
415 err := c.tracker.Track(trans)
417 xapp.Logger.Error("XAPP-SubReq Tracking error: %s", idstring(err, trans))
418 err = fmt.Errorf("Tracking failure")
422 subs, err := c.registry.AssignToSubscription(trans, subReqMsg, c.ResetTestFlag, c)
424 xapp.Logger.Error("XAPP-SubReq Assign error: %s", idstring(err, trans))
431 go c.handleSubscriptionCreate(subs, trans)
432 event, _ := trans.WaitEvent(0) //blocked wait as timeout is handled in subs side
436 switch themsg := event.(type) {
437 case *e2ap.E2APSubscriptionResponse:
440 case *e2ap.E2APSubscriptionFailure:
441 err = fmt.Errorf("E2 SubscriptionFailure received")
444 err = fmt.Errorf("unexpected E2 subscription response received")
448 err = fmt.Errorf("E2 subscription response timeout")
451 xapp.Logger.Error("XAPP-SubReq E2 subscription failed %s", idstring(err, trans, subs))
452 c.registry.RemoveFromSubscription(subs, trans, waitRouteCleanup_ms, c)
456 //-------------------------------------------------------------------
458 //-------------------------------------------------------------------
459 func (c *Control) sendUnsuccesfullResponseNotification(restSubId *string, restSubscription *RESTSubscription, xAppEventInstanceID int64, err error,
460 clientEndpoint *models.SubscriptionParamsClientEndpoint, trans *TransactionXapp) {
462 // Send notification to xApp that prosessing of a Subscription Request has failed.
463 e2EventInstanceID := (int64)(0)
464 errorCause := err.Error()
465 resp := &models.SubscriptionResponse{
466 SubscriptionID: restSubId,
467 SubscriptionInstances: []*models.SubscriptionInstance{
468 &models.SubscriptionInstance{E2EventInstanceID: &e2EventInstanceID,
469 ErrorCause: &errorCause,
470 XappEventInstanceID: &xAppEventInstanceID},
473 // Mark REST subscription request processed.
474 restSubscription.SetProcessed(err)
475 c.UpdateRESTSubscriptionInDB(*restSubId, restSubscription, false)
477 xapp.Logger.Info("Sending unsuccessful REST notification (cause %s) to endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v, %s",
478 errorCause, clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID, idstring(nil, trans))
480 xapp.Logger.Info("Sending unsuccessful REST notification (cause %s) to endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v",
481 errorCause, clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID)
484 c.UpdateCounter(cRestSubFailNotifToXapp)
485 xapp.Subscription.Notify(resp, *clientEndpoint)
488 //-------------------------------------------------------------------
490 //-------------------------------------------------------------------
491 func (c *Control) sendSuccesfullResponseNotification(restSubId *string, restSubscription *RESTSubscription, xAppEventInstanceID int64, e2EventInstanceID int64,
492 clientEndpoint *models.SubscriptionParamsClientEndpoint, trans *TransactionXapp) {
494 // Store successfully processed InstanceId for deletion
495 restSubscription.AddE2InstanceId((uint32)(e2EventInstanceID))
496 restSubscription.AddXappIdToE2Id(xAppEventInstanceID, e2EventInstanceID)
498 // Send notification to xApp that a Subscription Request has been processed.
499 resp := &models.SubscriptionResponse{
500 SubscriptionID: restSubId,
501 SubscriptionInstances: []*models.SubscriptionInstance{
502 &models.SubscriptionInstance{E2EventInstanceID: &e2EventInstanceID,
504 XappEventInstanceID: &xAppEventInstanceID},
507 // Mark REST subscription request processesd.
508 restSubscription.SetProcessed(nil)
509 c.UpdateRESTSubscriptionInDB(*restSubId, restSubscription, false)
510 xapp.Logger.Info("Sending successful REST notification to endpoint=%v:%v, XappEventInstanceID=%v, E2EventInstanceID=%v, %s",
511 clientEndpoint.Host, *clientEndpoint.HTTPPort, xAppEventInstanceID, e2EventInstanceID, idstring(nil, trans))
513 c.UpdateCounter(cRestSubNotifToXapp)
514 xapp.Subscription.Notify(resp, *clientEndpoint)
517 //-------------------------------------------------------------------
519 //-------------------------------------------------------------------
520 func (c *Control) SubscriptionDeleteHandlerCB(restSubId string) error {
523 c.UpdateCounter(cRestSubDelReqFromXapp)
525 xapp.Logger.Info("SubscriptionDeleteRequest from XAPP")
527 restSubscription, err := c.registry.GetRESTSubscription(restSubId, true)
529 xapp.Logger.Error("%s", err.Error())
530 if restSubscription == nil {
531 // Subscription was not found
534 if restSubscription.SubReqOngoing == true {
535 err := fmt.Errorf("Handling of the REST Subscription Request still ongoing %s", restSubId)
536 xapp.Logger.Error("%s", err.Error())
538 } else if restSubscription.SubDelReqOngoing == true {
539 // Previous request for same restSubId still ongoing
545 xAppRmrEndPoint := restSubscription.xAppRmrEndPoint
547 xapp.Logger.Info("Deleteting instances = %v", restSubscription.InstanceIds)
548 for _, instanceId := range restSubscription.InstanceIds {
549 xAppEventInstanceID, err := c.SubscriptionDeleteHandler(&restSubId, &xAppRmrEndPoint, &restSubscription.Meid, instanceId)
552 xapp.Logger.Error("%s", err.Error())
555 xapp.Logger.Info("Deleteting instanceId = %v", instanceId)
556 restSubscription.DeleteXappIdToE2Id(xAppEventInstanceID)
557 restSubscription.DeleteE2InstanceId(instanceId)
559 restDuplicateCtrl.DeleteLastKnownRestSubsIdBasedOnMd5sum(restSubscription.lastReqMd5sum)
560 c.registry.DeleteRESTSubscription(&restSubId)
561 c.RemoveRESTSubscriptionFromDb(restSubId)
564 c.UpdateCounter(cRestSubDelRespToXapp)
569 //-------------------------------------------------------------------
571 //-------------------------------------------------------------------
572 func (c *Control) SubscriptionDeleteHandler(restSubId *string, endPoint *string, meid *string, instanceId uint32) (int64, error) {
574 var xAppEventInstanceID int64
575 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{instanceId})
577 xapp.Logger.Info("Subscription Delete Handler subscription for restSubId=%v, E2EventInstanceID=%v not found %s",
578 restSubId, instanceId, idstring(err, nil))
579 return xAppEventInstanceID, nil
582 xAppEventInstanceID = int64(subs.ReqId.Id)
583 trans := c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(*endPoint), *restSubId, e2ap.RequestId{subs.ReqId.Id, 0}, &xapp.RMRMeid{RanName: *meid})
585 err := fmt.Errorf("XAPP-SubDelReq transaction not created. restSubId %s, endPoint %s, meid %s, instanceId %v", *restSubId, *endPoint, *meid, instanceId)
586 xapp.Logger.Error("%s", err.Error())
588 defer trans.Release()
590 err = c.tracker.Track(trans)
592 err := fmt.Errorf("XAPP-SubDelReq %s:", idstring(err, trans))
593 xapp.Logger.Error("%s", err.Error())
594 return xAppEventInstanceID, &time.ParseError{}
599 go c.handleSubscriptionDelete(subs, trans)
600 trans.WaitEvent(0) //blocked wait as timeout is handled in subs side
602 xapp.Logger.Debug("XAPP-SubDelReq: Handling event %s ", idstring(nil, trans, subs))
604 c.registry.RemoveFromSubscription(subs, trans, waitRouteCleanup_ms, c)
606 return xAppEventInstanceID, nil
609 //-------------------------------------------------------------------
611 //-------------------------------------------------------------------
612 func (c *Control) QueryHandler() (models.SubscriptionList, error) {
613 xapp.Logger.Info("QueryHandler() called")
617 return c.registry.QueryHandler()
620 func (c *Control) TestRestHandler(w http.ResponseWriter, r *http.Request) {
621 xapp.Logger.Info("TestRestHandler() called")
623 pathParams := mux.Vars(r)
624 s := pathParams["testId"]
626 // This can be used to delete single subscription from db
627 if contains := strings.Contains(s, "deletesubid="); contains == true {
628 var splits = strings.Split(s, "=")
629 if subId, err := strconv.ParseInt(splits[1], 10, 64); err == nil {
630 xapp.Logger.Info("RemoveSubscriptionFromSdl() called. subId = %v", subId)
631 c.RemoveSubscriptionFromSdl(uint32(subId))
636 // This can be used to remove all subscriptions db from
638 xapp.Logger.Info("RemoveAllSubscriptionsFromSdl() called")
639 c.RemoveAllSubscriptionsFromSdl()
640 c.RemoveAllRESTSubscriptionsFromSdl()
644 // This is meant to cause submgr's restart in testing
646 xapp.Logger.Info("os.Exit(1) called")
650 xapp.Logger.Info("Unsupported rest command received %s", s)
653 //-------------------------------------------------------------------
655 //-------------------------------------------------------------------
657 func (c *Control) rmrSendToE2T(desc string, subs *Subscription, trans *TransactionSubs) (err error) {
658 params := &xapp.RMRParams{}
659 params.Mtype = trans.GetMtype()
660 params.SubId = int(subs.GetReqId().InstanceId)
662 params.Meid = subs.GetMeid()
664 params.PayloadLen = len(trans.Payload.Buf)
665 params.Payload = trans.Payload.Buf
667 xapp.Logger.Info("MSG to E2T: %s %s %s", desc, trans.String(), params.String())
668 err = c.SendWithRetry(params, false, 5)
670 xapp.Logger.Error("rmrSendToE2T: Send failed: %+v", err)
675 func (c *Control) rmrSendToXapp(desc string, subs *Subscription, trans *TransactionXapp) (err error) {
677 params := &xapp.RMRParams{}
678 params.Mtype = trans.GetMtype()
679 params.SubId = int(subs.GetReqId().InstanceId)
680 params.Xid = trans.GetXid()
681 params.Meid = trans.GetMeid()
683 params.PayloadLen = len(trans.Payload.Buf)
684 params.Payload = trans.Payload.Buf
686 xapp.Logger.Info("MSG to XAPP: %s %s %s", desc, trans.String(), params.String())
687 err = c.SendWithRetry(params, false, 5)
689 xapp.Logger.Error("rmrSendToXapp: Send failed: %+v", err)
694 func (c *Control) Consume(msg *xapp.RMRParams) (err error) {
695 if c.RMRClient == nil {
696 err = fmt.Errorf("Rmr object nil can handle %s", msg.String())
697 xapp.Logger.Error("%s", err.Error())
702 defer c.RMRClient.Free(msg.Mbuf)
704 // xapp-frame might use direct access to c buffer and
705 // when msg.Mbuf is freed, someone might take it into use
706 // and payload data might be invalid inside message handle function
708 // subscriptions won't load system a lot so there is no
709 // real performance hit by cloning buffer into new go byte slice
710 cPay := append(msg.Payload[:0:0], msg.Payload...)
712 msg.PayloadLen = len(cPay)
715 case xapp.RIC_SUB_REQ:
716 go c.handleXAPPSubscriptionRequest(msg)
717 case xapp.RIC_SUB_RESP:
718 go c.handleE2TSubscriptionResponse(msg)
719 case xapp.RIC_SUB_FAILURE:
720 go c.handleE2TSubscriptionFailure(msg)
721 case xapp.RIC_SUB_DEL_REQ:
722 go c.handleXAPPSubscriptionDeleteRequest(msg)
723 case xapp.RIC_SUB_DEL_RESP:
724 go c.handleE2TSubscriptionDeleteResponse(msg)
725 case xapp.RIC_SUB_DEL_FAILURE:
726 go c.handleE2TSubscriptionDeleteFailure(msg)
728 xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype)
733 //-------------------------------------------------------------------
734 // handle from XAPP Subscription Request
735 //------------------------------------------------------------------
736 func (c *Control) handleXAPPSubscriptionRequest(params *xapp.RMRParams) {
737 xapp.Logger.Info("MSG from XAPP: %s", params.String())
738 c.UpdateCounter(cSubReqFromXapp)
740 subReqMsg, err := c.e2ap.UnpackSubscriptionRequest(params.Payload)
742 xapp.Logger.Error("XAPP-SubReq: %s", idstring(err, params))
746 trans := c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(params.Src), params.Xid, subReqMsg.RequestId, params.Meid)
748 xapp.Logger.Error("XAPP-SubReq: %s", idstring(fmt.Errorf("transaction not created"), params))
751 defer trans.Release()
753 if err = c.tracker.Track(trans); err != nil {
754 xapp.Logger.Error("XAPP-SubReq: %s", idstring(err, trans))
758 //TODO handle subscription toward e2term inside AssignToSubscription / hide handleSubscriptionCreate in it?
759 subs, err := c.registry.AssignToSubscription(trans, subReqMsg, c.ResetTestFlag, c)
761 xapp.Logger.Error("XAPP-SubReq: %s", idstring(err, trans))
765 c.wakeSubscriptionRequest(subs, trans)
768 //-------------------------------------------------------------------
769 // Wake Subscription Request to E2node
770 //------------------------------------------------------------------
771 func (c *Control) wakeSubscriptionRequest(subs *Subscription, trans *TransactionXapp) {
773 go c.handleSubscriptionCreate(subs, trans)
774 event, _ := trans.WaitEvent(0) //blocked wait as timeout is handled in subs side
777 switch themsg := event.(type) {
778 case *e2ap.E2APSubscriptionResponse:
779 themsg.RequestId.Id = trans.RequestId.Id
780 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionResponse(themsg)
783 c.UpdateCounter(cSubRespToXapp)
784 c.rmrSendToXapp("", subs, trans)
787 case *e2ap.E2APSubscriptionFailure:
788 themsg.RequestId.Id = trans.RequestId.Id
789 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionFailure(themsg)
791 c.UpdateCounter(cSubFailToXapp)
792 c.rmrSendToXapp("", subs, trans)
798 xapp.Logger.Info("XAPP-SubReq: failed %s", idstring(err, trans, subs))
799 //c.registry.RemoveFromSubscription(subs, trans, 5*time.Second)
802 //-------------------------------------------------------------------
803 // handle from XAPP Subscription Delete Request
804 //------------------------------------------------------------------
805 func (c *Control) handleXAPPSubscriptionDeleteRequest(params *xapp.RMRParams) {
806 xapp.Logger.Info("MSG from XAPP: %s", params.String())
807 c.UpdateCounter(cSubDelReqFromXapp)
809 subDelReqMsg, err := c.e2ap.UnpackSubscriptionDeleteRequest(params.Payload)
811 xapp.Logger.Error("XAPP-SubDelReq %s", idstring(err, params))
815 trans := c.tracker.NewXappTransaction(xapp.NewRmrEndpoint(params.Src), params.Xid, subDelReqMsg.RequestId, params.Meid)
817 xapp.Logger.Error("XAPP-SubDelReq: %s", idstring(fmt.Errorf("transaction not created"), params))
820 defer trans.Release()
822 err = c.tracker.Track(trans)
824 xapp.Logger.Error("XAPP-SubReq: %s", idstring(err, trans))
828 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{trans.GetSubId()})
830 xapp.Logger.Error("XAPP-SubDelReq: %s", idstring(err, trans))
837 go c.handleSubscriptionDelete(subs, trans)
838 trans.WaitEvent(0) //blocked wait as timeout is handled in subs side
840 xapp.Logger.Debug("XAPP-SubDelReq: Handling event %s ", idstring(nil, trans, subs))
842 if subs.NoRespToXapp == true {
843 // Do no send delete responses to xapps due to submgr restart is deleting uncompleted subscriptions
847 // Whatever is received success, fail or timeout, send successful delete response
848 subDelRespMsg := &e2ap.E2APSubscriptionDeleteResponse{}
849 subDelRespMsg.RequestId.Id = trans.RequestId.Id
850 subDelRespMsg.RequestId.InstanceId = subs.GetReqId().RequestId.InstanceId
851 subDelRespMsg.FunctionId = subs.SubReqMsg.FunctionId
852 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionDeleteResponse(subDelRespMsg)
854 c.UpdateCounter(cSubDelRespToXapp)
855 c.rmrSendToXapp("", subs, trans)
858 //TODO handle subscription toward e2term insiged RemoveFromSubscription / hide handleSubscriptionDelete in it?
859 //c.registry.RemoveFromSubscription(subs, trans, 5*time.Second)
862 //-------------------------------------------------------------------
863 // SUBS CREATE Handling
864 //-------------------------------------------------------------------
865 func (c *Control) handleSubscriptionCreate(subs *Subscription, parentTrans *TransactionXapp) {
867 var removeSubscriptionFromDb bool = false
868 trans := c.tracker.NewSubsTransaction(subs)
869 subs.WaitTransactionTurn(trans)
870 defer subs.ReleaseTransactionTurn(trans)
871 defer trans.Release()
873 xapp.Logger.Debug("SUBS-SubReq: Handling %s ", idstring(nil, trans, subs, parentTrans))
875 subRfMsg, valid := subs.GetCachedResponse()
876 if subRfMsg == nil && valid == true {
877 event := c.sendE2TSubscriptionRequest(subs, trans, parentTrans)
878 switch event.(type) {
879 case *e2ap.E2APSubscriptionResponse:
880 subRfMsg, valid = subs.SetCachedResponse(event, true)
881 subs.SubRespRcvd = true
882 case *e2ap.E2APSubscriptionFailure:
883 removeSubscriptionFromDb = true
884 subRfMsg, valid = subs.SetCachedResponse(event, false)
885 xapp.Logger.Info("SUBS-SubReq: internal delete due failure event(%s) %s", typeofSubsMessage(event), idstring(nil, trans, subs, parentTrans))
886 c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
887 case *SubmgrRestartTestEvent:
888 // This simulates that no response has been received and after restart subscriptions are restored from db
889 xapp.Logger.Debug("Test restart flag is active. Dropping this transaction to test restart case")
892 xapp.Logger.Info("SUBS-SubReq: internal delete due default event(%s) %s", typeofSubsMessage(event), idstring(nil, trans, subs, parentTrans))
893 removeSubscriptionFromDb = true
894 subRfMsg, valid = subs.SetCachedResponse(nil, false)
895 c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
897 xapp.Logger.Debug("SUBS-SubReq: Handling (e2t response %s) %s", typeofSubsMessage(subRfMsg), idstring(nil, trans, subs, parentTrans))
899 xapp.Logger.Debug("SUBS-SubReq: Handling (cached response %s) %s", typeofSubsMessage(subRfMsg), idstring(nil, trans, subs, parentTrans))
902 //Now RemoveFromSubscription in here to avoid race conditions (mostly concerns delete)
904 c.registry.RemoveFromSubscription(subs, parentTrans, waitRouteCleanup_ms, c)
907 c.UpdateSubscriptionInDB(subs, removeSubscriptionFromDb)
908 parentTrans.SendEvent(subRfMsg, 0)
911 //-------------------------------------------------------------------
912 // SUBS DELETE Handling
913 //-------------------------------------------------------------------
915 func (c *Control) handleSubscriptionDelete(subs *Subscription, parentTrans *TransactionXapp) {
917 trans := c.tracker.NewSubsTransaction(subs)
918 subs.WaitTransactionTurn(trans)
919 defer subs.ReleaseTransactionTurn(trans)
920 defer trans.Release()
922 xapp.Logger.Debug("SUBS-SubDelReq: Handling %s", idstring(nil, trans, subs, parentTrans))
926 if subs.valid && subs.EpList.HasEndpoint(parentTrans.GetEndpoint()) && subs.EpList.Size() == 1 {
929 c.sendE2TSubscriptionDeleteRequest(subs, trans, parentTrans)
933 //Now RemoveFromSubscription in here to avoid race conditions (mostly concerns delete)
934 // If parallel deletes ongoing both might pass earlier sendE2TSubscriptionDeleteRequest(...) if
935 // RemoveFromSubscription locates in caller side (now in handleXAPPSubscriptionDeleteRequest(...))
936 c.registry.RemoveFromSubscription(subs, parentTrans, waitRouteCleanup_ms, c)
937 c.registry.UpdateSubscriptionToDb(subs, c)
938 parentTrans.SendEvent(nil, 0)
941 //-------------------------------------------------------------------
942 // send to E2T Subscription Request
943 //-------------------------------------------------------------------
944 func (c *Control) sendE2TSubscriptionRequest(subs *Subscription, trans *TransactionSubs, parentTrans *TransactionXapp) interface{} {
946 var event interface{} = nil
947 var timedOut bool = false
948 const ricRequestorId = 123
950 subReqMsg := subs.SubReqMsg
951 subReqMsg.RequestId = subs.GetReqId().RequestId
952 subReqMsg.RequestId.Id = ricRequestorId
953 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionRequest(subReqMsg)
955 xapp.Logger.Error("SUBS-SubReq: %s", idstring(err, trans, subs, parentTrans))
959 // Write uncompleted subscrition in db. If no response for subscrition it need to be re-processed (deleted) after restart
960 c.WriteSubscriptionToDb(subs)
962 for retries := uint64(0); retries < e2tMaxSubReqTryCount; retries++ {
963 desc := fmt.Sprintf("(retry %d)", retries)
965 c.UpdateCounter(cSubReqToE2)
967 c.UpdateCounter(cSubReReqToE2)
969 c.rmrSendToE2T(desc, subs, trans)
970 if subs.DoNotWaitSubResp == false {
971 event, timedOut = trans.WaitEvent(e2tSubReqTimeout)
973 c.UpdateCounter(cSubReqTimerExpiry)
977 // Simulating case where subscrition request has been sent but response has not been received before restart
978 event = &SubmgrRestartTestEvent{}
982 xapp.Logger.Debug("SUBS-SubReq: Response handling event(%s) %s", typeofSubsMessage(event), idstring(nil, trans, subs, parentTrans))
986 //-------------------------------------------------------------------
987 // send to E2T Subscription Delete Request
988 //-------------------------------------------------------------------
990 func (c *Control) sendE2TSubscriptionDeleteRequest(subs *Subscription, trans *TransactionSubs, parentTrans *TransactionXapp) interface{} {
992 var event interface{}
994 const ricRequestorId = 123
996 subDelReqMsg := &e2ap.E2APSubscriptionDeleteRequest{}
997 subDelReqMsg.RequestId = subs.GetReqId().RequestId
998 subDelReqMsg.RequestId.Id = ricRequestorId
999 subDelReqMsg.FunctionId = subs.SubReqMsg.FunctionId
1000 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionDeleteRequest(subDelReqMsg)
1002 xapp.Logger.Error("SUBS-SubDelReq: %s", idstring(err, trans, subs, parentTrans))
1006 for retries := uint64(0); retries < e2tMaxSubDelReqTryCount; retries++ {
1007 desc := fmt.Sprintf("(retry %d)", retries)
1009 c.UpdateCounter(cSubDelReqToE2)
1011 c.UpdateCounter(cSubDelReReqToE2)
1013 c.rmrSendToE2T(desc, subs, trans)
1014 event, timedOut = trans.WaitEvent(e2tSubDelReqTime)
1016 c.UpdateCounter(cSubDelReqTimerExpiry)
1021 xapp.Logger.Debug("SUBS-SubDelReq: Response handling event(%s) %s", typeofSubsMessage(event), idstring(nil, trans, subs, parentTrans))
1025 //-------------------------------------------------------------------
1026 // handle from E2T Subscription Response
1027 //-------------------------------------------------------------------
1028 func (c *Control) handleE2TSubscriptionResponse(params *xapp.RMRParams) {
1029 xapp.Logger.Info("MSG from E2T: %s", params.String())
1030 c.UpdateCounter(cSubRespFromE2)
1032 subRespMsg, err := c.e2ap.UnpackSubscriptionResponse(params.Payload)
1034 xapp.Logger.Error("MSG-SubResp %s", idstring(err, params))
1037 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{subRespMsg.RequestId.InstanceId})
1039 xapp.Logger.Error("MSG-SubResp: %s", idstring(err, params))
1042 trans := subs.GetTransaction()
1044 err = fmt.Errorf("Ongoing transaction not found")
1045 xapp.Logger.Error("MSG-SubResp: %s", idstring(err, params, subs))
1048 sendOk, timedOut := trans.SendEvent(subRespMsg, e2tRecvMsgTimeout)
1049 if sendOk == false {
1050 err = fmt.Errorf("Passing event to transaction failed: sendOk(%t) timedOut(%t)", sendOk, timedOut)
1051 xapp.Logger.Error("MSG-SubResp: %s", idstring(err, trans, subs))
1056 //-------------------------------------------------------------------
1057 // handle from E2T Subscription Failure
1058 //-------------------------------------------------------------------
1059 func (c *Control) handleE2TSubscriptionFailure(params *xapp.RMRParams) {
1060 xapp.Logger.Info("MSG from E2T: %s", params.String())
1061 c.UpdateCounter(cSubFailFromE2)
1062 subFailMsg, err := c.e2ap.UnpackSubscriptionFailure(params.Payload)
1064 xapp.Logger.Error("MSG-SubFail %s", idstring(err, params))
1067 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{subFailMsg.RequestId.InstanceId})
1069 xapp.Logger.Error("MSG-SubFail: %s", idstring(err, params))
1072 trans := subs.GetTransaction()
1074 err = fmt.Errorf("Ongoing transaction not found")
1075 xapp.Logger.Error("MSG-SubFail: %s", idstring(err, params, subs))
1078 sendOk, timedOut := trans.SendEvent(subFailMsg, e2tRecvMsgTimeout)
1079 if sendOk == false {
1080 err = fmt.Errorf("Passing event to transaction failed: sendOk(%t) timedOut(%t)", sendOk, timedOut)
1081 xapp.Logger.Error("MSG-SubFail: %s", idstring(err, trans, subs))
1086 //-------------------------------------------------------------------
1087 // handle from E2T Subscription Delete Response
1088 //-------------------------------------------------------------------
1089 func (c *Control) handleE2TSubscriptionDeleteResponse(params *xapp.RMRParams) (err error) {
1090 xapp.Logger.Info("MSG from E2T: %s", params.String())
1091 c.UpdateCounter(cSubDelRespFromE2)
1092 subDelRespMsg, err := c.e2ap.UnpackSubscriptionDeleteResponse(params.Payload)
1094 xapp.Logger.Error("MSG-SubDelResp: %s", idstring(err, params))
1097 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{subDelRespMsg.RequestId.InstanceId})
1099 xapp.Logger.Error("MSG-SubDelResp: %s", idstring(err, params))
1102 trans := subs.GetTransaction()
1104 err = fmt.Errorf("Ongoing transaction not found")
1105 xapp.Logger.Error("MSG-SubDelResp: %s", idstring(err, params, subs))
1108 sendOk, timedOut := trans.SendEvent(subDelRespMsg, e2tRecvMsgTimeout)
1109 if sendOk == false {
1110 err = fmt.Errorf("Passing event to transaction failed: sendOk(%t) timedOut(%t)", sendOk, timedOut)
1111 xapp.Logger.Error("MSG-SubDelResp: %s", idstring(err, trans, subs))
1116 //-------------------------------------------------------------------
1117 // handle from E2T Subscription Delete Failure
1118 //-------------------------------------------------------------------
1119 func (c *Control) handleE2TSubscriptionDeleteFailure(params *xapp.RMRParams) {
1120 xapp.Logger.Info("MSG from E2T: %s", params.String())
1121 c.UpdateCounter(cSubDelFailFromE2)
1122 subDelFailMsg, err := c.e2ap.UnpackSubscriptionDeleteFailure(params.Payload)
1124 xapp.Logger.Error("MSG-SubDelFail: %s", idstring(err, params))
1127 subs, err := c.registry.GetSubscriptionFirstMatch([]uint32{subDelFailMsg.RequestId.InstanceId})
1129 xapp.Logger.Error("MSG-SubDelFail: %s", idstring(err, params))
1132 trans := subs.GetTransaction()
1134 err = fmt.Errorf("Ongoing transaction not found")
1135 xapp.Logger.Error("MSG-SubDelFail: %s", idstring(err, params, subs))
1138 sendOk, timedOut := trans.SendEvent(subDelFailMsg, e2tRecvMsgTimeout)
1139 if sendOk == false {
1140 err = fmt.Errorf("Passing event to transaction failed: sendOk(%t) timedOut(%t)", sendOk, timedOut)
1141 xapp.Logger.Error("MSG-SubDelFail: %s", idstring(err, trans, subs))
1146 //-------------------------------------------------------------------
1148 //-------------------------------------------------------------------
1149 func typeofSubsMessage(v interface{}) string {
1154 //case *e2ap.E2APSubscriptionRequest:
1156 case *e2ap.E2APSubscriptionResponse:
1158 case *e2ap.E2APSubscriptionFailure:
1160 //case *e2ap.E2APSubscriptionDeleteRequest:
1161 // return "SubDelReq"
1162 case *e2ap.E2APSubscriptionDeleteResponse:
1164 case *e2ap.E2APSubscriptionDeleteFailure:
1171 //-------------------------------------------------------------------
1173 //-------------------------------------------------------------------
1174 func (c *Control) WriteSubscriptionToDb(subs *Subscription) {
1175 xapp.Logger.Debug("WriteSubscriptionToDb() subId = %v", subs.ReqId.InstanceId)
1176 err := c.WriteSubscriptionToSdl(subs.ReqId.InstanceId, subs)
1178 xapp.Logger.Error("%v", err)
1182 //-------------------------------------------------------------------
1184 //-------------------------------------------------------------------
1185 func (c *Control) UpdateSubscriptionInDB(subs *Subscription, removeSubscriptionFromDb bool) {
1187 if removeSubscriptionFromDb == true {
1188 // Subscription was written in db already when subscription request was sent to BTS, except for merged request
1189 c.RemoveSubscriptionFromDb(subs)
1191 // Update is needed for successful response and merge case here
1192 if subs.RetryFromXapp == false {
1193 c.WriteSubscriptionToDb(subs)
1196 subs.RetryFromXapp = false
1199 //-------------------------------------------------------------------
1201 //-------------------------------------------------------------------
1202 func (c *Control) RemoveSubscriptionFromDb(subs *Subscription) {
1203 xapp.Logger.Debug("RemoveSubscriptionFromDb() subId = %v", subs.ReqId.InstanceId)
1204 err := c.RemoveSubscriptionFromSdl(subs.ReqId.InstanceId)
1206 xapp.Logger.Error("%v", err)
1210 //-------------------------------------------------------------------
1212 //-------------------------------------------------------------------
1213 func (c *Control) WriteRESTSubscriptionToDb(restSubId string, restSubs *RESTSubscription) {
1214 xapp.Logger.Debug("WriteRESTSubscriptionToDb() restSubId = %s", restSubId)
1215 err := c.WriteRESTSubscriptionToSdl(restSubId, restSubs)
1217 xapp.Logger.Error("%v", err)
1221 //-------------------------------------------------------------------
1223 //-------------------------------------------------------------------
1224 func (c *Control) UpdateRESTSubscriptionInDB(restSubId string, restSubs *RESTSubscription, removeRestSubscriptionFromDb bool) {
1226 if removeRestSubscriptionFromDb == true {
1227 // Subscription was written in db already when subscription request was sent to BTS, except for merged request
1228 c.RemoveRESTSubscriptionFromDb(restSubId)
1230 c.WriteRESTSubscriptionToDb(restSubId, restSubs)
1234 //-------------------------------------------------------------------
1236 //-------------------------------------------------------------------
1237 func (c *Control) RemoveRESTSubscriptionFromDb(restSubId string) {
1238 xapp.Logger.Debug("RemoveRESTSubscriptionFromDb() restSubId = %s", restSubId)
1239 err := c.RemoveRESTSubscriptionFromSdl(restSubId)
1241 xapp.Logger.Error("%v", err)
1245 func (c *Control) SendSubscriptionDeleteReq(subs *Subscription) {
1247 const ricRequestorId = 123
1248 xapp.Logger.Debug("Sending subscription delete due to restart. subId = %v", subs.ReqId.InstanceId)
1250 // Send delete for every endpoint in the subscription
1251 subDelReqMsg := &e2ap.E2APSubscriptionDeleteRequest{}
1252 subDelReqMsg.RequestId = subs.GetReqId().RequestId
1253 subDelReqMsg.RequestId.Id = ricRequestorId
1254 subDelReqMsg.FunctionId = subs.SubReqMsg.FunctionId
1255 mType, payload, err := c.e2ap.PackSubscriptionDeleteRequest(subDelReqMsg)
1257 xapp.Logger.Error("SendSubscriptionDeleteReq() %s", idstring(err))
1260 for _, endPoint := range subs.EpList.Endpoints {
1261 params := &xapp.RMRParams{}
1262 params.Mtype = mType
1263 params.SubId = int(subs.GetReqId().InstanceId)
1265 params.Meid = subs.Meid
1266 params.Src = endPoint.String()
1267 params.PayloadLen = len(payload.Buf)
1268 params.Payload = payload.Buf
1270 subs.DeleteFromDb = true
1271 c.handleXAPPSubscriptionDeleteRequest(params)
1275 func (c *Control) PrintRESTSubscriptionRequest(p *models.SubscriptionParams) {
1277 fmt.Println("CRESTSubscriptionRequest")
1279 if p.SubscriptionID != "" {
1280 fmt.Println(" SubscriptionID = ", p.SubscriptionID)
1282 fmt.Println(" SubscriptionID = ''")
1285 fmt.Printf(" ClientEndpoint.Host = %s\n", p.ClientEndpoint.Host)
1287 if p.ClientEndpoint.HTTPPort != nil {
1288 fmt.Printf(" ClientEndpoint.HTTPPort = %v\n", *p.ClientEndpoint.HTTPPort)
1290 fmt.Println(" ClientEndpoint.HTTPPort = nil")
1293 if p.ClientEndpoint.RMRPort != nil {
1294 fmt.Printf(" ClientEndpoint.RMRPort = %v\n", *p.ClientEndpoint.RMRPort)
1296 fmt.Println(" ClientEndpoint.RMRPort = nil")
1300 fmt.Printf(" Meid = %s\n", *p.Meid)
1302 fmt.Println(" Meid = nil")
1305 for _, subscriptionDetail := range p.SubscriptionDetails {
1306 if p.RANFunctionID != nil {
1307 fmt.Printf(" RANFunctionID = %v\n", *p.RANFunctionID)
1309 fmt.Println(" RANFunctionID = nil")
1311 fmt.Printf(" SubscriptionDetail.XappEventInstanceID = %v\n", *subscriptionDetail.XappEventInstanceID)
1312 fmt.Printf(" SubscriptionDetail.EventTriggers = %v\n", subscriptionDetail.EventTriggers)
1314 for _, actionToBeSetup := range subscriptionDetail.ActionToBeSetupList {
1315 fmt.Printf(" SubscriptionDetail.ActionToBeSetup.ActionID = %v\n", *actionToBeSetup.ActionID)
1316 fmt.Printf(" SubscriptionDetail.ActionToBeSetup.ActionType = %s\n", *actionToBeSetup.ActionType)
1317 fmt.Printf(" SubscriptionDetail.ActionToBeSetup.ActionDefinition = %v\n", actionToBeSetup.ActionDefinition)
1319 if actionToBeSetup.SubsequentAction != nil {
1320 fmt.Printf(" SubscriptionDetail.ActionToBeSetup.SubsequentAction.SubsequentActionType = %s\n", *actionToBeSetup.SubsequentAction.SubsequentActionType)
1321 fmt.Printf(" SubscriptionDetail.ActionToBeSetup..SubsequentAction.TimeToWait = %s\n", *actionToBeSetup.SubsequentAction.TimeToWait)
1323 fmt.Println(" SubscriptionDetail.ActionToBeSetup.SubsequentAction = nil")