From 2a08feca830537e70eab2b39b2e561ccc0b5d026 Mon Sep 17 00:00:00 2001 From: DanB Date: Mon, 12 Sep 2016 19:54:37 +0200 Subject: [PATCH] ARIEvent with value caching, pass attributes to Stasis app --- .../asterisk/etc/asterisk/extensions.conf | 2 +- sessionmanager/sma_event.go | 37 +++++++++++++++---- sessionmanager/sma_event_test.go | 31 ++++++++++------ sessionmanager/smasterisk.go | 35 +++++++++++++----- 4 files changed, 77 insertions(+), 28 deletions(-) diff --git a/data/tutorials/asterisk_events/asterisk/etc/asterisk/extensions.conf b/data/tutorials/asterisk_events/asterisk/etc/asterisk/extensions.conf index 734d8fb41..5e7c39442 100755 --- a/data/tutorials/asterisk_events/asterisk/etc/asterisk/extensions.conf +++ b/data/tutorials/asterisk_events/asterisk/etc/asterisk/extensions.conf @@ -1,6 +1,6 @@ [internal] exten => _1XXX,1,NoOp() - same => n,Stasis(cgrates_auth) + same => n,Stasis(cgrates_auth,cgr_reqtype=*prepaid,cgr_destination=${EXTEN}) same => n,Dial(PJSIP/${EXTEN},30) same => n,Hangup() diff --git a/sessionmanager/sma_event.go b/sessionmanager/sma_event.go index d63fb3d39..08c8ecdf2 100644 --- a/sessionmanager/sma_event.go +++ b/sessionmanager/sma_event.go @@ -17,19 +17,42 @@ along with this program. If not, see */ package sessionmanager +import ( + "github.com/cgrates/cgrates/utils" +) + const ( ARIStasisStart = "StasisStart" ) -type ARIEvent map[string]interface{} +func NewARIEvent(ev map[string]interface{}) *ARIEvent { + return &ARIEvent{ev: ev} +} -func (aev ARIEvent) Type() string { - typ, _ := aev["type"].(string) - return typ +type ARIEvent struct { // Standalone struct so we can cache the fields while we parse them + ev map[string]interface{} + evType *string + channelID *string +} + +func (aev *ARIEvent) Type() string { + if aev.evType == nil { + typ, _ := aev.ev["type"].(string) + aev.evType = utils.StringPointer(typ) + } + return *aev.evType } func (aev ARIEvent) ChannelID() string { - channelData, _ := aev["channel"].(map[string]interface{}) - channelID, _ := channelData["id"].(string) - return channelID + if aev.channelID == nil { + channelData, _ := aev.ev["channel"].(map[string]interface{}) + channelID, _ := channelData["id"].(string) + aev.channelID = utils.StringPointer(channelID) + } + return *aev.channelID +} + +func (aev ARIEvent) AsSMGenericSessionStart() (smgEv SMGenericEvent, err error) { + smgEv = SMGenericEvent{utils.EVENT_NAME: utils.CGR_SESSION_START} + return smgEv, nil } diff --git a/sessionmanager/sma_event_test.go b/sessionmanager/sma_event_test.go index 8073e9eb9..9129e4fcf 100644 --- a/sessionmanager/sma_event_test.go +++ b/sessionmanager/sma_event_test.go @@ -23,23 +23,28 @@ import ( ) var ( - stasisStart = `{"application":"cgrates_auth","type":"StasisStart","timestamp":"2016-09-12T13:53:48.919+0200","args":[],"channel":{"id":"1473681228.6","state":"Ring","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":""},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":2},"creationtime":"2016-09-12T13:53:48.918+0200"}}` - channelStateChange = `{"application":"cgrates_auth","type":"ChannelStateChange","timestamp":"2016-09-12T13:53:52.110+0200","channel":{"id":"1473681228.6","state":"Up","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":"1002"},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":3},"creationtime":"2016-09-12T13:53:48.918+0200"}}` - channelDestroyed = `{"type":"ChannelDestroyed","timestamp":"2016-09-12T13:54:27.335+0200","application":"cgrates_auth","cause_txt":"Normal Clearing","channel":{"id":"1473681228.6","state":"Up","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":"1002"},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":3},"creationtime":"2016-09-12T13:53:48.918+0200"},"cause":16}` + stasisStart = `{"application":"cgrates_auth","type":"StasisStart","timestamp":"2016-09-12T13:53:48.919+0200","args":[],"channel":{"id":"1473681228.6","state":"Ring","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":""},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":2},"creationtime":"2016-09-12T13:53:48.918+0200"}}` + channelStateChange = `{"application":"cgrates_auth","type":"ChannelStateChange","timestamp":"2016-09-12T13:53:52.110+0200","channel":{"id":"1473681228.6","state":"Up","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":"1002"},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":3},"creationtime":"2016-09-12T13:53:48.918+0200"}}` + channelAnsweredDestroyed = `{"type":"ChannelDestroyed","timestamp":"2016-09-12T13:54:27.335+0200","application":"cgrates_auth","cause_txt":"Normal Clearing","channel":{"id":"1473681228.6","state":"Up","name":"PJSIP/1001-00000004","caller":{"name":"1001","number":"1001"},"language":"en","connected":{"name":"","number":"1002"},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":3},"creationtime":"2016-09-12T13:53:48.918+0200"},"cause":16}` + channelUnansweredDestroyed = `{"type":"ChannelDestroyed","timestamp":"2016-09-12T18:00:18.121+0200","application":"cgrates_auth","cause_txt":"Normal Clearing","channel":{"id":"1473696018.2","state":"Ring","name":"PJSIP/1002-00000002","caller":{"name":"1002","number":"1002"},"language":"en","connected":{"name":"","number":""},"accountcode":"","dialplan":{"context":"internal","exten":"1002","priority":2},"creationtime":"2016-09-12T18:00:18.109+0200"},"cause":16}` ) func TestSMAEventType(t *testing.T) { var ev map[string]interface{} if err := json.Unmarshal([]byte(stasisStart), &ev); err != nil { t.Error(err) - } else if ARIEvent(ev).Type() != "StasisStart" { - t.Error("Received type:", ARIEvent(ev).Type()) + } + ariEv := NewARIEvent(ev) + if ariEv.Type() != "StasisStart" { + t.Error("Received type:", ariEv.Type()) } ev = make(map[string]interface{}) // Clear previous data if err := json.Unmarshal([]byte("{}"), &ev); err != nil { t.Error(err) - } else if ARIEvent(ev).Type() != "" { - t.Error("Received type:", ARIEvent(ev).Type()) + } + ariEv = NewARIEvent(ev) + if ariEv.Type() != "" { + t.Error("Received type:", ariEv.Type()) } } @@ -47,13 +52,17 @@ func TestSMAEventChannelID(t *testing.T) { var ev map[string]interface{} if err := json.Unmarshal([]byte(stasisStart), &ev); err != nil { t.Error(err) - } else if ARIEvent(ev).ChannelID() != "1473681228.6" { - t.Error("Received type:", ARIEvent(ev).ChannelID()) + } + ariEv := NewARIEvent(ev) + if ariEv.ChannelID() != "1473681228.6" { + t.Error("Received type:", ariEv.ChannelID()) } ev = make(map[string]interface{}) // Clear previous data if err := json.Unmarshal([]byte("{}"), &ev); err != nil { t.Error(err) - } else if ARIEvent(ev).ChannelID() != "" { - t.Error("Received type:", ARIEvent(ev).ChannelID()) + } + ariEv = NewARIEvent(ev) + if ariEv.ChannelID() != "" { + t.Error("Received type:", ariEv.ChannelID()) } } diff --git a/sessionmanager/smasterisk.go b/sessionmanager/smasterisk.go index ec071c957..a0703bd3f 100644 --- a/sessionmanager/smasterisk.go +++ b/sessionmanager/smasterisk.go @@ -66,21 +66,38 @@ func (sma *SMAsterisk) ListenAndServe() (err error) { case err = <-sma.astErrChan: return err case astRawEv := <-sma.astEvChan: - ariEvent := ARIEvent(astRawEv) - if ariEvent.Type() == ARIStasisStart { - channelID := ariEvent.ChannelID() - if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/applications/%s/subscription?eventSource=channel:%s", - sma.cgrCfg.SMAsteriskCfg().AsteriskConns[sma.astConnIdx].Address, CGRAuthAPP, channelID), nil); err != nil { - } - if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/channels/%s/continue", - sma.cgrCfg.SMAsteriskCfg().AsteriskConns[sma.astConnIdx].Address, channelID), url.Values{"channelId": {channelID}}); err != nil { - } + ariEvent := NewARIEvent(astRawEv) + switch ariEvent.Type() { + case ARIStasisStart: + go sma.handleStasisStart(ariEvent) } } } panic(" ListenAndServe out of select") } +func (sma *SMAsterisk) handleStasisStart(ev *ARIEvent) { + channelID := ev.ChannelID() + + if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/applications/%s/subscription?eventSource=channel:%s", + sma.cgrCfg.SMAsteriskCfg().AsteriskConns[sma.astConnIdx].Address, CGRAuthAPP, channelID), nil); err != nil { + + utils.Logger.Err(fmt.Sprintf(" Error: %s when subscribing to events for channelID: %s", err.Error(), channelID)) + + if _, err := sma.astConn.Call(aringo.HTTP_DELETE, fmt.Sprintf("http://%s/ari/channels/%s", + sma.cgrCfg.SMAsteriskCfg().AsteriskConns[sma.astConnIdx].Address, channelID), url.Values{"reason": {"congestion"}}); err != nil { + utils.Logger.Err(fmt.Sprintf(" Error: %s when attempting to disconnect channelID: %s", err.Error(), channelID)) + return + } + + } + + if _, err := sma.astConn.Call(aringo.HTTP_POST, fmt.Sprintf("http://%s/ari/channels/%s/continue", + sma.cgrCfg.SMAsteriskCfg().AsteriskConns[sma.astConnIdx].Address, channelID), url.Values{"channelId": {channelID}}); err != nil { + } + +} + // Called to shutdown the service func (rls *SMAsterisk) ServiceShutdown() error { return nil