ARIEvent with value caching, pass attributes to Stasis app

This commit is contained in:
DanB
2016-09-12 19:54:37 +02:00
parent e47931e842
commit 2a08feca83
4 changed files with 77 additions and 28 deletions

View File

@@ -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()

View File

@@ -17,19 +17,42 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
*/
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
}

View File

@@ -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())
}
}

View File

@@ -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("<SMAsterisk> 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("<SMAsterisk> 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("<SMAsterisk> 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