blob: cc176c2b711c1c58370a648da6a39f721b50a6ea [file] [log] [blame]
kalnagy45114752019-06-18 14:40:39 +02001/*
2==================================================================================
3 Copyright (c) 2019 AT&T Intellectual Property.
4 Copyright (c) 2019 Nokia
5
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
9
10 http://www.apache.org/licenses/LICENSE-2.0
11
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==================================================================================
18*/
19
20package control
21
kalnagy45114752019-06-18 14:40:39 +020022import (
Juha Hyttinene406a342020-01-13 13:02:26 +020023 "fmt"
Juha Hyttinen86a46202020-01-14 12:49:09 +020024 "gerrit.o-ran-sc.org/r/ric-plt/e2ap/pkg/e2ap"
kalnagy93cc3e22019-09-19 11:29:29 +020025 rtmgrclient "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client"
26 rtmgrhandle "gerrit.o-ran-sc.org/r/ric-plt/submgr/pkg/rtmgr_client/handle"
kalnagy1455c852019-10-21 13:06:23 +020027 "gerrit.o-ran-sc.org/r/ric-plt/xapp-frame/pkg/xapp"
28 httptransport "github.com/go-openapi/runtime/client"
29 "github.com/go-openapi/strfmt"
30 "github.com/spf13/viper"
Juha Hyttinenff8dccd2019-12-10 14:34:07 +020031 "sync"
Peter Szilagyifbc56f92019-07-23 19:29:46 +000032 "time"
kalnagy45114752019-06-18 14:40:39 +020033)
34
Juha Hyttinene406a342020-01-13 13:02:26 +020035//-----------------------------------------------------------------------------
36//
37//-----------------------------------------------------------------------------
38
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +020039var subReqTime time.Duration = 5 * time.Second
Anssi Mannila8046c702020-01-02 13:39:05 +020040var subDelReqTime time.Duration = 5 * time.Second
41var maxSubReqTryCount uint64 = 2 // Initial try + retry
42var maxSubDelReqTryCount uint64 = 2 // Initial try + retry
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020043
kalnagy45114752019-06-18 14:40:39 +020044type Control struct {
Juha Hyttinenc65f5b02019-12-30 14:24:04 +020045 e2ap *E2ap
46 registry *Registry
Juha Hyttinenc65f5b02019-12-30 14:24:04 +020047 tracker *Tracker
48 timerMap *TimerMap
49 rmrSendMutex sync.Mutex
Juha Hyttinen47b842b2020-01-08 13:01:52 +020050 msgCounter uint64
kalnagy93cc3e22019-09-19 11:29:29 +020051}
52
53type RMRMeid struct {
Juha Hyttinenff8dccd2019-12-10 14:34:07 +020054 PlmnID string
55 EnbID string
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020056 RanName string
kalnagy93cc3e22019-09-19 11:29:29 +020057}
58
kalnagy93cc3e22019-09-19 11:29:29 +020059const (
60 CREATE Action = 0
kalnagy1455c852019-10-21 13:06:23 +020061 MERGE Action = 1
Anssi Mannila90fa0212019-12-12 10:47:47 +020062 NONE Action = 2
kalnagy93cc3e22019-09-19 11:29:29 +020063 DELETE Action = 3
64)
Peter Szilagyifbc56f92019-07-23 19:29:46 +000065
66func init() {
Anssi Mannila8046c702020-01-02 13:39:05 +020067 xapp.Logger.Info("SUBMGR")
Peter Szilagyifbc56f92019-07-23 19:29:46 +000068 viper.AutomaticEnv()
69 viper.SetEnvPrefix("submgr")
70 viper.AllowEmptyEnv(true)
kalnagy45114752019-06-18 14:40:39 +020071}
72
Juha Hyttinenff8dccd2019-12-10 14:34:07 +020073func NewControl() *Control {
Juha Hyttinen0388dd92020-01-09 14:14:16 +020074
Juha Hyttinen56e03832020-01-14 17:08:43 +020075 transport := httptransport.New(viper.GetString("rtmgr.HostAddr")+":"+viper.GetString("rtmgr.port"), viper.GetString("rtmgr.baseUrl"), []string{"http"})
76 client := rtmgrclient.New(transport, strfmt.Default)
77 handle := rtmgrhandle.NewProvideXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
78 deleteHandle := rtmgrhandle.NewDeleteXappSubscriptionHandleParamsWithTimeout(10 * time.Second)
79 rtmgrClient := RtmgrClient{client, handle, deleteHandle}
80
Peter Szilagyifbc56f92019-07-23 19:29:46 +000081 registry := new(Registry)
Anssi Mannila5c161a92020-01-15 15:40:57 +020082 registry.Initialize()
Juha Hyttinen56e03832020-01-14 17:08:43 +020083 registry.rtmgrClient = &rtmgrClient
kalnagy93cc3e22019-09-19 11:29:29 +020084
Balint Uvegese9608cd2019-09-20 18:00:32 +000085 tracker := new(Tracker)
86 tracker.Init()
87
Anssi Mannila2e99e2f2019-12-05 13:57:06 +020088 timerMap := new(TimerMap)
89 timerMap.Init()
90
Juha Hyttinenff8dccd2019-12-10 14:34:07 +020091 return &Control{e2ap: new(E2ap),
Juha Hyttinen56e03832020-01-14 17:08:43 +020092 registry: registry,
93 tracker: tracker,
94 timerMap: timerMap,
95 msgCounter: 0,
Juha Hyttinenff8dccd2019-12-10 14:34:07 +020096 }
kalnagy45114752019-06-18 14:40:39 +020097}
98
99func (c *Control) Run() {
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000100 xapp.Run(c)
kalnagy45114752019-06-18 14:40:39 +0200101}
102
Juha Hyttinene406a342020-01-13 13:02:26 +0200103func (c *Control) rmrSendRaw(desc string, params *RMRParams) (err error) {
104
105 xapp.Logger.Info("%s: %s", desc, params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200106 status := false
107 i := 1
Juha Hyttinenff8dccd2019-12-10 14:34:07 +0200108 for ; i <= 10 && status == false; i++ {
Anssi Mannila90fa0212019-12-12 10:47:47 +0200109 c.rmrSendMutex.Lock()
Juha Hyttinene406a342020-01-13 13:02:26 +0200110 status = xapp.Rmr.Send(params.RMRParams, false)
Anssi Mannila90fa0212019-12-12 10:47:47 +0200111 c.rmrSendMutex.Unlock()
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200112 if status == false {
Juha Hyttinene406a342020-01-13 13:02:26 +0200113 xapp.Logger.Info("rmr.Send() failed. Retry count %d, %s", i, params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200114 time.Sleep(500 * time.Millisecond)
115 }
116 }
117 if status == false {
Juha Hyttinene406a342020-01-13 13:02:26 +0200118 err = fmt.Errorf("rmr.Send() failed. Retry count %d, %s", i, params.String())
119 xapp.Logger.Error("%s: %s", desc, err.Error())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200120 xapp.Rmr.Free(params.Mbuf)
121 }
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000122 return
kalnagy45114752019-06-18 14:40:39 +0200123}
124
Juha Hyttinen63284a22020-01-15 10:45:11 +0200125func (c *Control) rmrSend(desc string, subs *Subscription, trans *Transaction) (err error) {
Juha Hyttinene406a342020-01-13 13:02:26 +0200126 params := &RMRParams{&xapp.RMRParams{}}
127 params.Mtype = trans.GetMtype()
128 params.SubId = int(subs.GetSubId())
Juha Hyttinen86a46202020-01-14 12:49:09 +0200129 params.Xid = ""
Juha Hyttinene406a342020-01-13 13:02:26 +0200130 params.Meid = subs.GetMeid()
131 params.Src = ""
Juha Hyttinen63284a22020-01-15 10:45:11 +0200132 params.PayloadLen = len(trans.Payload.Buf)
133 params.Payload = trans.Payload.Buf
Juha Hyttinene406a342020-01-13 13:02:26 +0200134 params.Mbuf = nil
135
136 return c.rmrSendRaw(desc, params)
kalnagye0018682019-09-26 16:28:25 +0200137}
138
Juha Hyttinen63284a22020-01-15 10:45:11 +0200139func (c *Control) rmrReplyToSender(desc string, subs *Subscription, trans *Transaction) (err error) {
Juha Hyttinene406a342020-01-13 13:02:26 +0200140 params := &RMRParams{&xapp.RMRParams{}}
Juha Hyttinen63284a22020-01-15 10:45:11 +0200141 params.Mtype = trans.GetMtype()
Juha Hyttinene406a342020-01-13 13:02:26 +0200142 params.SubId = int(subs.GetSubId())
143 params.Xid = trans.GetXid()
Juha Hyttinen86a46202020-01-14 12:49:09 +0200144 params.Meid = trans.GetMeid()
Juha Hyttinene406a342020-01-13 13:02:26 +0200145 params.Src = ""
Juha Hyttinen63284a22020-01-15 10:45:11 +0200146 params.PayloadLen = len(trans.Payload.Buf)
147 params.Payload = trans.Payload.Buf
Juha Hyttinene406a342020-01-13 13:02:26 +0200148 params.Mbuf = nil
149
150 return c.rmrSendRaw(desc, params)
151}
152
153func (c *Control) Consume(params *xapp.RMRParams) (err error) {
154 xapp.Rmr.Free(params.Mbuf)
155 params.Mbuf = nil
Juha Hyttinene406a342020-01-13 13:02:26 +0200156 msg := &RMRParams{params}
Juha Hyttinen47b842b2020-01-08 13:01:52 +0200157 c.msgCounter++
Anssi Mannila90fa0212019-12-12 10:47:47 +0200158 switch msg.Mtype {
159 case xapp.RICMessageTypes["RIC_SUB_REQ"]:
160 go c.handleSubscriptionRequest(msg)
161 case xapp.RICMessageTypes["RIC_SUB_RESP"]:
162 go c.handleSubscriptionResponse(msg)
163 case xapp.RICMessageTypes["RIC_SUB_FAILURE"]:
164 go c.handleSubscriptionFailure(msg)
165 case xapp.RICMessageTypes["RIC_SUB_DEL_REQ"]:
166 go c.handleSubscriptionDeleteRequest(msg)
167 case xapp.RICMessageTypes["RIC_SUB_DEL_RESP"]:
168 go c.handleSubscriptionDeleteResponse(msg)
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200169 case xapp.RICMessageTypes["RIC_SUB_DEL_FAILURE"]:
170 go c.handleSubscriptionDeleteFailure(msg)
Anssi Mannila90fa0212019-12-12 10:47:47 +0200171 default:
172 xapp.Logger.Info("Unknown Message Type '%d', discarding", msg.Mtype)
Balint Uvegescd3881b2019-10-02 15:01:43 +0000173 }
Juha Hyttinen86a46202020-01-14 12:49:09 +0200174
Anssi Mannila90fa0212019-12-12 10:47:47 +0200175 return nil
Balint Uvegescd3881b2019-10-02 15:01:43 +0000176}
177
Juha Hyttinene406a342020-01-13 13:02:26 +0200178func (c *Control) handleSubscriptionRequest(params *RMRParams) {
179 xapp.Logger.Info("SubReq from xapp: %s", params.String())
kalnagy93cc3e22019-09-19 11:29:29 +0200180
Juha Hyttinen86a46202020-01-14 12:49:09 +0200181 //
182 //
183 //
184 trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
Juha Hyttinen86a46202020-01-14 12:49:09 +0200185 params.Xid,
186 params.Meid,
187 false,
188 true)
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200189
Juha Hyttinen0388dd92020-01-09 14:14:16 +0200190 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200191 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), params.String())
Juha Hyttinenff8dccd2019-12-10 14:34:07 +0200192 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200193 }
kalnagy93cc3e22019-09-19 11:29:29 +0200194
Juha Hyttinene406a342020-01-13 13:02:26 +0200195 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200196 //
197 //
Juha Hyttinen86a46202020-01-14 12:49:09 +0200198 trans.SubReqMsg, err = c.e2ap.UnpackSubscriptionRequest(params.Payload)
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000199 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200200 xapp.Logger.Error("SubReq: %s Dropping this msg. %s", err.Error(), trans)
201 trans.Release()
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000202 return
203 }
kalnagy93cc3e22019-09-19 11:29:29 +0200204
Juha Hyttinen86a46202020-01-14 12:49:09 +0200205 //
206 //
207 //
208 subs, err := c.registry.ReserveSubscription(&trans.RmrEndpoint, trans.Meid)
kalnagy93cc3e22019-09-19 11:29:29 +0200209 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200210 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
211 trans.Release()
Juha Hyttinenc65f5b02019-12-30 14:24:04 +0200212 return
Anssi Mannila90fa0212019-12-12 10:47:47 +0200213 }
kalnagy93cc3e22019-09-19 11:29:29 +0200214
Juha Hyttinene406a342020-01-13 13:02:26 +0200215 err = subs.SetTransaction(trans)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200216 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200217 xapp.Logger.Error("SubReq: %s, Dropping this msg. %s", err.Error(), trans)
Juha Hyttinen56e03832020-01-14 17:08:43 +0200218 subs.Release()
Juha Hyttinene406a342020-01-13 13:02:26 +0200219 trans.Release()
220 return
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200221 }
Juha Hyttinene406a342020-01-13 13:02:26 +0200222
Juha Hyttinen86a46202020-01-14 12:49:09 +0200223 trans.SubReqMsg.RequestId.Seq = uint32(subs.GetSubId())
224
225 //
226 // TODO: subscription create is in fact owned by subscription and not transaction.
227 // Transaction is toward xapp while Subscription is toward ran.
228 // In merge several xapps may wake transactions, while only one subscription
229 // toward ran occurs -> subscription owns subscription creation toward ran
230 //
231 // This is intermediate solution while improving message handling
232 //
Juha Hyttinen63284a22020-01-15 10:45:11 +0200233 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionRequest(trans.SubReqMsg)
Juha Hyttinen86a46202020-01-14 12:49:09 +0200234 if err != nil {
235 xapp.Logger.Error("SubReq: %s for trans %s", err.Error(), trans)
Juha Hyttinen56e03832020-01-14 17:08:43 +0200236 subs.Release()
Juha Hyttinen86a46202020-01-14 12:49:09 +0200237 trans.Release()
238 return
239 }
240
Juha Hyttinen63284a22020-01-15 10:45:11 +0200241 c.rmrSend("SubReq: SubReq to E2T", subs, trans)
Juha Hyttinene406a342020-01-13 13:02:26 +0200242
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200243 c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, FirstTry, c.handleSubscriptionRequestTimer)
Juha Hyttinene406a342020-01-13 13:02:26 +0200244 xapp.Logger.Debug("SubReq: Debugging trans table = %v", c.tracker.transactionXappTable)
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000245 return
kalnagy45114752019-06-18 14:40:39 +0200246}
247
Juha Hyttinene406a342020-01-13 13:02:26 +0200248func (c *Control) handleSubscriptionResponse(params *RMRParams) {
249 xapp.Logger.Info("SubResp from E2T: %s", params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200250
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200251 //
252 //
253 //
254 SubRespMsg, err := c.e2ap.UnpackSubscriptionResponse(params.Payload)
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000255 if err != nil {
Juha Hyttinen662f68d2020-01-15 14:49:18 +0200256 xapp.Logger.Error("SubResp: %s Dropping this msg. %s", err.Error(), params.String())
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000257 return
258 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200259
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200260 //
261 //
262 //
263 subs := c.registry.GetSubscription(uint16(SubRespMsg.RequestId.Seq))
264 if subs == nil && params.SubId > 0 {
265 subs = c.registry.GetSubscription(uint16(params.SubId))
266 }
267
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200268 if subs == nil {
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200269 xapp.Logger.Error("SubResp: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubRespMsg.RequestId.Seq, params.SubId, params.String())
270 return
271 }
272 xapp.Logger.Info("SubResp: subscription found payloadSeqNum: %d, SubId: %d", SubRespMsg.RequestId.Seq, subs.GetSubId())
273
274 //
275 //
276 //
277 trans := subs.GetTransaction()
278 if trans == nil {
279 xapp.Logger.Error("SubResp: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
Peter Szilagyifbc56f92019-07-23 19:29:46 +0000280 return
281 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200282
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200283 trans.SubRespMsg = SubRespMsg
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200284
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200285 //
286 //
287 //
288 c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200289
Juha Hyttinene406a342020-01-13 13:02:26 +0200290 responseReceived := trans.CheckResponseReceived()
Anssi Mannila8046c702020-01-02 13:39:05 +0200291 if responseReceived == true {
292 // Subscription timer already received
293 return
294 }
Anssi Mannila8046c702020-01-02 13:39:05 +0200295
Juha Hyttinen63284a22020-01-15 10:45:11 +0200296 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionResponse(trans.SubRespMsg)
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200297 if err != nil {
298 xapp.Logger.Error("SubResp: %s for trans %s", err.Error(), trans)
299 trans.Release()
300 return
301 }
302
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200303 subs.Confirmed()
Juha Hyttinene406a342020-01-13 13:02:26 +0200304 trans.Release()
Juha Hyttinen63284a22020-01-15 10:45:11 +0200305 c.rmrReplyToSender("SubResp: SubResp to xapp", subs, trans)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200306 return
307}
308
Juha Hyttinene406a342020-01-13 13:02:26 +0200309func (c *Control) handleSubscriptionFailure(params *RMRParams) {
310 xapp.Logger.Info("SubFail from E2T: %s", params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200311
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200312 //
313 //
314 //
315 SubFailMsg, err := c.e2ap.UnpackSubscriptionFailure(params.Payload)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200316 if err != nil {
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200317 xapp.Logger.Error("SubFail: %s Dropping this msg. %s", err.Error(), params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200318 return
319 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200320
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200321 //
322 //
323 //
324 subs := c.registry.GetSubscription(uint16(SubFailMsg.RequestId.Seq))
325 if subs == nil && params.SubId > 0 {
326 subs = c.registry.GetSubscription(uint16(params.SubId))
327 }
328
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200329 if subs == nil {
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200330 xapp.Logger.Error("SubFail: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubFailMsg.RequestId.Seq, params.SubId, params.String())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200331 return
332 }
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200333 xapp.Logger.Info("SubFail: subscription found payloadSeqNum: %d, SubId: %d", SubFailMsg.RequestId.Seq, subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200334
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200335 //
336 //
337 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200338 trans := subs.GetTransaction()
339 if trans == nil {
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200340 xapp.Logger.Error("SubFail: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200341 return
342 }
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200343 trans.SubFailMsg = SubFailMsg
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200344
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200345 //
346 //
347 //
348 c.timerMap.StopTimer("RIC_SUB_REQ", int(subs.GetSubId()))
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200349
Juha Hyttinene406a342020-01-13 13:02:26 +0200350 responseReceived := trans.CheckResponseReceived()
Juha Hyttinenff8dccd2019-12-10 14:34:07 +0200351 if err != nil {
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200352 return
353 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200354
Anssi Mannila8046c702020-01-02 13:39:05 +0200355 if responseReceived == true {
356 // Subscription timer already received
357 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200358 }
359
Juha Hyttinen63284a22020-01-15 10:45:11 +0200360 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionFailure(trans.SubFailMsg)
Juha Hyttinen375c1412020-01-14 20:17:50 +0200361 if err == nil {
Juha Hyttinen63284a22020-01-15 10:45:11 +0200362 c.rmrReplyToSender("SubFail: SubFail to xapp", subs, trans)
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200363 time.Sleep(3 * time.Second)
Juha Hyttinen375c1412020-01-14 20:17:50 +0200364 } else {
365 //TODO error handling improvement
366 xapp.Logger.Error("SubFail: %s for trans %s (continuing cleaning)", err.Error(), trans)
Juha Hyttinen60bfcf92020-01-14 15:14:24 +0200367 }
Anssi Mannilaa189c862020-01-10 11:36:35 +0200368
Juha Hyttinene406a342020-01-13 13:02:26 +0200369 trans.Release()
Juha Hyttinen56e03832020-01-14 17:08:43 +0200370 subs.Release()
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200371 return
372}
373
Anssi Mannila8046c702020-01-02 13:39:05 +0200374func (c *Control) handleSubscriptionRequestTimer(strId string, nbrId int, tryCount uint64) {
Juha Hyttinene406a342020-01-13 13:02:26 +0200375 xapp.Logger.Info("SubReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200376
Juha Hyttinene406a342020-01-13 13:02:26 +0200377 subs := c.registry.GetSubscription(uint16(nbrId))
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200378 if subs == nil {
Juha Hyttinene406a342020-01-13 13:02:26 +0200379 xapp.Logger.Error("SubReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200380 return
381 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200382
Juha Hyttinene406a342020-01-13 13:02:26 +0200383 trans := subs.GetTransaction()
384 if trans == nil {
385 xapp.Logger.Error("SubReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200386 return
387 }
388
Juha Hyttinene406a342020-01-13 13:02:26 +0200389 responseReceived := trans.CheckResponseReceived()
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200390
Anssi Mannila8046c702020-01-02 13:39:05 +0200391 if responseReceived == true {
392 // Subscription Response or Failure already received
393 return
394 }
395
396 if tryCount < maxSubReqTryCount {
Juha Hyttinen63284a22020-01-15 10:45:11 +0200397 xapp.Logger.Info("SubReq timeout: subs: %s trans: %s", subs, trans)
Anssi Mannila8046c702020-01-02 13:39:05 +0200398
Juha Hyttinene406a342020-01-13 13:02:26 +0200399 trans.RetryTransaction()
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200400
Juha Hyttinen63284a22020-01-15 10:45:11 +0200401 c.rmrSend("SubReq timeout: SubReq to E2T", subs, trans)
Anssi Mannila8046c702020-01-02 13:39:05 +0200402
403 tryCount++
Juha Hyttinene406a342020-01-13 13:02:26 +0200404 c.timerMap.StartTimer("RIC_SUB_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionRequestTimer)
Anssi Mannila8046c702020-01-02 13:39:05 +0200405 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200406 }
Anssi Mannila8046c702020-01-02 13:39:05 +0200407
Juha Hyttinen375c1412020-01-14 20:17:50 +0200408 // Release CREATE transaction
Juha Hyttinene406a342020-01-13 13:02:26 +0200409 trans.Release()
Anssi Mannila8046c702020-01-02 13:39:05 +0200410
Juha Hyttinene406a342020-01-13 13:02:26 +0200411 // Create DELETE transaction (internal and no messages toward xapp)
Juha Hyttinen86a46202020-01-14 12:49:09 +0200412 deltrans, err := c.tracker.TrackTransaction(&trans.RmrEndpoint,
Juha Hyttinen86a46202020-01-14 12:49:09 +0200413 trans.GetXid(),
414 trans.GetMeid(),
415 false,
416 false)
417
Anssi Mannila8046c702020-01-02 13:39:05 +0200418 if err != nil {
Juha Hyttinene406a342020-01-13 13:02:26 +0200419 xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
Juha Hyttinen86a46202020-01-14 12:49:09 +0200420 //TODO improve error handling. Important at least in merge
Juha Hyttinen56e03832020-01-14 17:08:43 +0200421 subs.Release()
Anssi Mannila8046c702020-01-02 13:39:05 +0200422 return
423 }
424
Juha Hyttinen86a46202020-01-14 12:49:09 +0200425 deltrans.SubDelReqMsg = &e2ap.E2APSubscriptionDeleteRequest{}
426 deltrans.SubDelReqMsg.RequestId.Id = trans.SubReqMsg.RequestId.Id
427 deltrans.SubDelReqMsg.RequestId.Seq = uint32(subs.GetSubId())
428 deltrans.SubDelReqMsg.FunctionId = trans.SubReqMsg.FunctionId
Juha Hyttinen63284a22020-01-15 10:45:11 +0200429 deltrans.Mtype, deltrans.Payload, err = c.e2ap.PackSubscriptionDeleteRequest(deltrans.SubDelReqMsg)
Juha Hyttinen86a46202020-01-14 12:49:09 +0200430 if err != nil {
431 xapp.Logger.Error("SubReq timeout: Packing SubDelReq failed. Err: %v", err)
432 //TODO improve error handling. Important at least in merge
433 deltrans.Release()
Juha Hyttinen56e03832020-01-14 17:08:43 +0200434 subs.Release()
Juha Hyttinen86a46202020-01-14 12:49:09 +0200435 return
436 }
Juha Hyttinen86a46202020-01-14 12:49:09 +0200437
Juha Hyttinene406a342020-01-13 13:02:26 +0200438 err = subs.SetTransaction(deltrans)
Anssi Mannila8046c702020-01-02 13:39:05 +0200439 if err != nil {
Juha Hyttinene406a342020-01-13 13:02:26 +0200440 xapp.Logger.Error("SubReq timeout: %s, Dropping this msg.", err.Error())
Juha Hyttinen86a46202020-01-14 12:49:09 +0200441 //TODO improve error handling. Important at least in merge
Juha Hyttinene406a342020-01-13 13:02:26 +0200442 deltrans.Release()
443 return
Anssi Mannila8046c702020-01-02 13:39:05 +0200444 }
Juha Hyttinene406a342020-01-13 13:02:26 +0200445
Juha Hyttinen63284a22020-01-15 10:45:11 +0200446 c.rmrSend("SubReq timer: SubDelReq to E2T", subs, deltrans)
Juha Hyttinene406a342020-01-13 13:02:26 +0200447 c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
kalnagy93cc3e22019-09-19 11:29:29 +0200448 return
449}
450
Juha Hyttinene406a342020-01-13 13:02:26 +0200451func (c *Control) handleSubscriptionDeleteRequest(params *RMRParams) {
452 xapp.Logger.Info("SubDelReq from xapp: %s", params.String())
kalnagy93cc3e22019-09-19 11:29:29 +0200453
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200454 //
455 //
456 //
Juha Hyttinen86a46202020-01-14 12:49:09 +0200457 trans, err := c.tracker.TrackTransaction(NewRmrEndpoint(params.Src),
Juha Hyttinen86a46202020-01-14 12:49:09 +0200458 params.Xid,
459 params.Meid,
460 false,
461 true)
462
Juha Hyttinene406a342020-01-13 13:02:26 +0200463 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200464 xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), params.String())
Juha Hyttinene406a342020-01-13 13:02:26 +0200465 return
kalnagy93cc3e22019-09-19 11:29:29 +0200466 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200467
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200468 //
469 //
470 //
471 trans.SubDelReqMsg, err = c.e2ap.UnpackSubscriptionDeleteRequest(params.Payload)
472 if err != nil {
473 xapp.Logger.Error("SubDelReq: %s Dropping this msg. %s", err.Error(), trans)
474 trans.Release()
475 return
kalnagy93cc3e22019-09-19 11:29:29 +0200476 }
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200477
Juha Hyttinenaafee7f2020-01-14 14:54:51 +0200478 //
479 //
480 //
481 subs := c.registry.GetSubscription(uint16(trans.SubDelReqMsg.RequestId.Seq))
Juha Hyttinen86a46202020-01-14 12:49:09 +0200482 if subs == nil && params.SubId > 0 {
483 subs = c.registry.GetSubscription(uint16(params.SubId))
484 }
Anssi Mannila26c922a2019-12-17 11:18:08 +0200485
Juha Hyttinene406a342020-01-13 13:02:26 +0200486 if subs == nil {
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200487 xapp.Logger.Error("SubDelReq: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
Juha Hyttinen86a46202020-01-14 12:49:09 +0200488 trans.Release()
Anssi Mannila90fa0212019-12-12 10:47:47 +0200489 return
kalnagy93cc3e22019-09-19 11:29:29 +0200490 }
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200491 xapp.Logger.Info("SubDelReq: subscription found payloadSeqNum: %d, SubId: %d. %s", trans.SubDelReqMsg.RequestId.Seq, params.SubId, trans)
Juha Hyttinene406a342020-01-13 13:02:26 +0200492
493 err = subs.SetTransaction(trans)
494 if err != nil {
Juha Hyttinen86a46202020-01-14 12:49:09 +0200495 xapp.Logger.Error("SubDelReq: %s, Dropping this msg. %s", err.Error(), trans)
Juha Hyttinene406a342020-01-13 13:02:26 +0200496 trans.Release()
497 return
498 }
499
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200500 //
501 // TODO: subscription delete is in fact owned by subscription and not transaction.
502 // Transaction is toward xapp while Subscription is toward ran.
503 // In merge several xapps may wake transactions, while only one subscription
504 // toward ran occurs -> subscription owns subscription creation toward ran
505 //
506 // This is intermediate solution while improving message handling
507 //
Juha Hyttinen63284a22020-01-15 10:45:11 +0200508 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionDeleteRequest(trans.SubDelReqMsg)
Juha Hyttinenb3dc1562020-01-14 14:32:17 +0200509 if err != nil {
510 xapp.Logger.Error("SubDelReq: %s for trans %s", err.Error(), trans)
511 trans.Release()
512 return
513 }
514
Juha Hyttinene406a342020-01-13 13:02:26 +0200515 subs.UnConfirmed()
516
Juha Hyttinen63284a22020-01-15 10:45:11 +0200517 c.rmrSend("SubDelReq: SubDelReq to E2T", subs, trans)
Juha Hyttinene406a342020-01-13 13:02:26 +0200518
519 c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subDelReqTime, FirstTry, c.handleSubscriptionDeleteRequestTimer)
kalnagye0018682019-09-26 16:28:25 +0200520 return
521}
522
Juha Hyttinene406a342020-01-13 13:02:26 +0200523func (c *Control) handleSubscriptionDeleteResponse(params *RMRParams) (err error) {
524 xapp.Logger.Info("SubDelResp from E2T:%s", params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200525
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200526 //
527 //
528 //
529 SubDelRespMsg, err := c.e2ap.UnpackSubscriptionDeleteResponse(params.Payload)
kalnagye0018682019-09-26 16:28:25 +0200530 if err != nil {
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200531 xapp.Logger.Error("SubDelResp: %s Dropping this msg. %s", err.Error(), params.String())
kalnagye0018682019-09-26 16:28:25 +0200532 return
533 }
kalnagye0018682019-09-26 16:28:25 +0200534
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200535 //
536 //
537 //
538 subs := c.registry.GetSubscription(uint16(SubDelRespMsg.RequestId.Seq))
539 if subs == nil && params.SubId > 0 {
540 subs = c.registry.GetSubscription(uint16(params.SubId))
541 }
542
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200543 if subs == nil {
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200544 xapp.Logger.Error("SubDelResp: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubDelRespMsg.RequestId.Seq, params.SubId, params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200545 return
546 }
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200547 xapp.Logger.Info("SubDelResp: subscription found payloadSeqNum: %d, SubId: %d", SubDelRespMsg.RequestId.Seq, subs.GetSubId())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200548
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200549 //
550 //
551 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200552 trans := subs.GetTransaction()
553 if trans == nil {
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200554 xapp.Logger.Error("SubDelResp: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200555 return
556 }
557
Juha Hyttinen4e7c8c52020-01-14 19:25:00 +0200558 trans.SubDelRespMsg = SubDelRespMsg
559
560 //
561 //
562 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200563 c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200564
Juha Hyttinene406a342020-01-13 13:02:26 +0200565 responseReceived := trans.CheckResponseReceived()
Anssi Mannila8046c702020-01-02 13:39:05 +0200566 if responseReceived == true {
567 // Subscription Delete timer already received
568 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200569 }
570
Juha Hyttinen375c1412020-01-14 20:17:50 +0200571 c.sendSubscriptionDeleteResponse("SubDelResp", trans, subs)
kalnagye0018682019-09-26 16:28:25 +0200572 return
573}
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200574
Juha Hyttinene406a342020-01-13 13:02:26 +0200575func (c *Control) handleSubscriptionDeleteFailure(params *RMRParams) {
576 xapp.Logger.Info("SubDelFail from E2T:%s", params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200577
Juha Hyttinen375c1412020-01-14 20:17:50 +0200578 //
579 //
580 //
581 SubDelFailMsg, err := c.e2ap.UnpackSubscriptionDeleteFailure(params.Payload)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200582 if err != nil {
Juha Hyttinen375c1412020-01-14 20:17:50 +0200583 xapp.Logger.Error("SubDelFail: %s Dropping this msg. %s", err.Error(), params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200584 return
585 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200586
Juha Hyttinen375c1412020-01-14 20:17:50 +0200587 //
588 //
589 //
590 subs := c.registry.GetSubscription(uint16(SubDelFailMsg.RequestId.Seq))
591 if subs == nil && params.SubId > 0 {
592 subs = c.registry.GetSubscription(uint16(params.SubId))
593 }
594
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200595 if subs == nil {
Juha Hyttinen375c1412020-01-14 20:17:50 +0200596 xapp.Logger.Error("SubDelFail: Not valid subscription found payloadSeqNum: %d, SubId: %d. Dropping this msg. %s", SubDelFailMsg.RequestId.Seq, params.SubId, params.String())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200597 return
598 }
Juha Hyttinen375c1412020-01-14 20:17:50 +0200599 xapp.Logger.Info("SubDelFail: subscription found payloadSeqNum: %d, SubId: %d", SubDelFailMsg.RequestId.Seq, subs.GetSubId())
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200600
Juha Hyttinen375c1412020-01-14 20:17:50 +0200601 //
602 //
603 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200604 trans := subs.GetTransaction()
605 if trans == nil {
Juha Hyttinen375c1412020-01-14 20:17:50 +0200606 xapp.Logger.Error("SubDelFail: Unknown trans. Dropping this msg. SubId: %d", subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200607 return
608 }
Juha Hyttinen375c1412020-01-14 20:17:50 +0200609 trans.SubDelFailMsg = SubDelFailMsg
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200610
Juha Hyttinen375c1412020-01-14 20:17:50 +0200611 //
612 //
613 //
Juha Hyttinene406a342020-01-13 13:02:26 +0200614 c.timerMap.StopTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()))
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200615
Juha Hyttinene406a342020-01-13 13:02:26 +0200616 responseReceived := trans.CheckResponseReceived()
Anssi Mannila8046c702020-01-02 13:39:05 +0200617 if responseReceived == true {
618 // Subscription Delete timer already received
619 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200620 }
Anssi Mannila8046c702020-01-02 13:39:05 +0200621
Juha Hyttinen375c1412020-01-14 20:17:50 +0200622 c.sendSubscriptionDeleteResponse("SubDelFail", trans, subs)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200623 return
624}
625
Anssi Mannila8046c702020-01-02 13:39:05 +0200626func (c *Control) handleSubscriptionDeleteRequestTimer(strId string, nbrId int, tryCount uint64) {
Juha Hyttinene406a342020-01-13 13:02:26 +0200627 xapp.Logger.Info("SubDelReq timeout: subId: %v, tryCount: %v", nbrId, tryCount)
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200628
Juha Hyttinene406a342020-01-13 13:02:26 +0200629 subs := c.registry.GetSubscription(uint16(nbrId))
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200630 if subs == nil {
Juha Hyttinene406a342020-01-13 13:02:26 +0200631 xapp.Logger.Error("SubDelReq timeout: Unknown payloadSeqNum. Dropping this msg. SubId: %v", nbrId)
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200632 return
633 }
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200634
Juha Hyttinene406a342020-01-13 13:02:26 +0200635 trans := subs.GetTransaction()
636 if trans == nil {
637 xapp.Logger.Error("SubDelReq timeout: Unknown trans. Dropping this msg. SubId: %v", subs.GetSubId())
Juha Hyttinen0d064ec2020-01-09 09:08:53 +0200638 return
639 }
640
Juha Hyttinene406a342020-01-13 13:02:26 +0200641 responseReceived := trans.CheckResponseReceived()
Anssi Mannila8046c702020-01-02 13:39:05 +0200642 if responseReceived == true {
643 // Subscription Delete Response or Failure already received
644 return
Anssi Mannila2e99e2f2019-12-05 13:57:06 +0200645 }
Juha Hyttinenff8dccd2019-12-10 14:34:07 +0200646
Anssi Mannila8046c702020-01-02 13:39:05 +0200647 if tryCount < maxSubDelReqTryCount {
Anssi Mannila8046c702020-01-02 13:39:05 +0200648 // Set possible to handle new response for the subId
Juha Hyttinene406a342020-01-13 13:02:26 +0200649 trans.RetryTransaction()
Juha Hyttinen63284a22020-01-15 10:45:11 +0200650 c.rmrSend("SubDelReq timeout: SubDelReq to E2T", subs, trans)
Anssi Mannila8046c702020-01-02 13:39:05 +0200651 tryCount++
Juha Hyttinene406a342020-01-13 13:02:26 +0200652 c.timerMap.StartTimer("RIC_SUB_DEL_REQ", int(subs.GetSubId()), subReqTime, tryCount, c.handleSubscriptionDeleteRequestTimer)
Anssi Mannila8046c702020-01-02 13:39:05 +0200653 return
654 }
655
Juha Hyttinen375c1412020-01-14 20:17:50 +0200656 c.sendSubscriptionDeleteResponse("SubDelReq(timer)", trans, subs)
657 return
658}
659
660func (c *Control) sendSubscriptionDeleteResponse(desc string, trans *Transaction, subs *Subscription) {
661
Juha Hyttinene406a342020-01-13 13:02:26 +0200662 if trans.ForwardRespToXapp == true {
Juha Hyttinen375c1412020-01-14 20:17:50 +0200663 //Always generate SubDelResp
664 trans.SubDelRespMsg = &e2ap.E2APSubscriptionDeleteResponse{}
665 trans.SubDelRespMsg.RequestId.Id = trans.SubDelReqMsg.RequestId.Id
666 trans.SubDelRespMsg.RequestId.Seq = uint32(subs.GetSubId())
667 trans.SubDelRespMsg.FunctionId = trans.SubDelReqMsg.FunctionId
668
Juha Hyttinen93400722020-01-15 09:25:13 +0200669 var err error
Juha Hyttinen63284a22020-01-15 10:45:11 +0200670 trans.Mtype, trans.Payload, err = c.e2ap.PackSubscriptionDeleteResponse(trans.SubDelRespMsg)
Juha Hyttinen375c1412020-01-14 20:17:50 +0200671 if err == nil {
Juha Hyttinen63284a22020-01-15 10:45:11 +0200672 c.rmrReplyToSender(desc+": SubDelResp to xapp", subs, trans)
Juha Hyttinen375c1412020-01-14 20:17:50 +0200673 time.Sleep(3 * time.Second)
674 } else {
675 //TODO error handling improvement
676 xapp.Logger.Error("%s: %s for trans %s (continuing cleaning)", desc, err.Error(), trans)
Anssi Mannila8046c702020-01-02 13:39:05 +0200677 }
Anssi Mannila8046c702020-01-02 13:39:05 +0200678 }
Juha Hyttinen375c1412020-01-14 20:17:50 +0200679
Juha Hyttinene406a342020-01-13 13:02:26 +0200680 trans.Release()
Juha Hyttinen56e03832020-01-14 17:08:43 +0200681 subs.Release()
Anssi Mannilaf1d0eb62019-12-17 15:29:55 +0200682}