Added rar for diameter

This commit is contained in:
Trial97
2020-03-18 17:51:36 +02:00
committed by Dan Christian Bogos
parent c9c11788ce
commit 0d51f5d539
13 changed files with 209 additions and 3 deletions

View File

@@ -364,3 +364,8 @@ func (sma *AsteriskAgent) V1GetActiveSessionIDs(ignParam string,
return nil
}
// V1SendRAR is used to implement the sessions.BiRPClient interface
func (*AsteriskAgent) V1SendRAR(originID string, reply *string) (err error) {
return utils.ErrNotImplemented
}

View File

@@ -168,7 +168,8 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
return
}
// cache message for ASR
if da.cgrCfg.DiameterAgentCfg().ASRTemplate != "" {
if da.cgrCfg.DiameterAgentCfg().ASRTemplate != "" ||
da.cgrCfg.DiameterAgentCfg().RARTemplate != "" {
sessID, err := diamDP.FieldAsString([]string{"Session-Id"})
if err != nil {
utils.Logger.Warning(
@@ -419,7 +420,7 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
return true, nil
}
// rpcclient.ClientConnector interface
// Call implements rpcclient.ClientConnector interface
func (da *DiameterAgent) Call(serviceMethod string, args interface{}, reply interface{}) error {
return utils.RPCCall(da, serviceMethod, args, reply)
}
@@ -476,3 +477,49 @@ func (da *DiameterAgent) V1GetActiveSessionIDs(ignParam string,
sessionIDs *[]*sessions.SessionID) error {
return utils.ErrNotImplemented
}
// V1SendRAR sends a rar meseage to diameter client
func (da *DiameterAgent) V1SendRAR(originID string, reply *string) (err error) {
if originID == "" {
utils.Logger.Info(
fmt.Sprintf("<%s> cannot send RAR, missing session ID",
utils.DiameterAgent))
return utils.ErrMandatoryIeMissing
}
msg, has := engine.Cache.Get(utils.CacheDiameterMessages, originID)
if !has {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot retrieve message from cache with OriginID: <%s>",
utils.DiameterAgent, originID))
return utils.ErrMandatoryIeMissing
}
dmd := msg.(*diamMsgData)
aReq := NewAgentRequest(
newDADataProvider(dmd.c, dmd.m),
dmd.vars,
config.NewNavigableMap(nil),
config.NewNavigableMap(nil),
nil,
da.cgrCfg.GeneralCfg().DefaultTenant,
da.cgrCfg.GeneralCfg().DefaultTimezone, da.filterS, nil, nil)
if err = aReq.SetFields(da.cgrCfg.DiameterAgentCfg().Templates[da.cgrCfg.DiameterAgentCfg().RARTemplate]); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot send RAR with OriginID: <%s>, err: %s",
utils.DiameterAgent, originID, err.Error()))
return utils.ErrServerError
}
m := diam.NewRequest(dmd.m.Header.CommandCode,
dmd.m.Header.ApplicationID, dmd.m.Dictionary())
if err = updateDiamMsgFromNavMap(m, aReq.diamreq,
da.cgrCfg.GeneralCfg().DefaultTimezone); err != nil {
utils.Logger.Warning(
fmt.Sprintf("<%s> cannot send RAR with OriginID: <%s>, err: %s",
utils.DiameterAgent, originID, err.Error()))
return utils.ErrServerError
}
if err = writeOnConn(dmd.c, m); err != nil {
return utils.ErrServerError
}
*reply = utils.OK
return
}

View File

@@ -439,3 +439,8 @@ func (sm *FSsessions) Reload() {
sm.conns = make([]*fsock.FSock, len(sm.cfg.EventSocketConns))
sm.senderPools = make([]*fsock.FSockPool, len(sm.cfg.EventSocketConns))
}
// V1SendRAR is used to implement the sessions.BiRPClient interface
func (*FSsessions) V1SendRAR(originID string, reply *string) (err error) {
return utils.ErrNotImplemented
}

View File

@@ -423,3 +423,8 @@ func (ka *KamailioAgent) V1GetActiveSessionIDs(ignParam string, sessionIDs *[]*s
func (ka *KamailioAgent) Reload() {
ka.conns = make([]*kamevapi.KamEvapi, len(ka.cfg.EvapiConns))
}
// V1SendRAR is used to implement the sessions.BiRPClient interface
func (*KamailioAgent) V1SendRAR(originID string, reply *string) (err error) {
return utils.ErrNotImplemented
}

View File

@@ -141,3 +141,8 @@ func (ssv1 *SessionSv1) Call(serviceMethod string,
args interface{}, reply interface{}) error {
return utils.APIerRPCCall(ssv1, serviceMethod, args, reply)
}
// SendRAR sends the RAR for filterd sessions
func (smgv1 *SessionSv1) SendRAR(args *utils.SessionFilter, reply *string) error {
return smgv1.Ss.BiRPCv1SendRAR(nil, args, reply)
}

View File

@@ -52,6 +52,8 @@ func (ssv1 *SessionSv1) Handlers() map[string]interface{} {
utils.SessionSv1SetPassiveSession: ssv1.BiRPCv1SetPassiveSession,
utils.SessionSv1ActivateSessions: ssv1.BiRPCv1ActivateSessions,
utils.SessionSv1DeactivateSessions: ssv1.BiRPCv1DeactivateSessions,
utils.SessionSv1SendRAR: ssv1.BiRPCV1SendRAR,
}
}
@@ -162,3 +164,9 @@ func (ssv1 *SessionSv1) BiRPCv1DeactivateSessions(clnt *rpc2.Client,
args *utils.SessionIDsWithArgsDispatcher, reply *string) error {
return ssv1.Ss.BiRPCv1DeactivateSessions(clnt, args, reply)
}
// BiRPCV1SendRAR sends the RAR for filterd sessions
func (ssv1 *SessionSv1) BiRPCV1SendRAR(clnt *rpc2.Client,
args *utils.SessionFilter, reply *string) error {
return ssv1.Ss.BiRPCv1SendRAR(clnt, args, reply)
}

View File

@@ -415,6 +415,7 @@ const CGRATES_CFG_JSON = `
"concurrent_requests": -1, // limit the number of active requests processed by the server <-1|0-n>
"synced_conn_requests": false, // process one request at the time per connection
"asr_template": "", // enable AbortSession message being sent to client on DisconnectSession
"rar_template": "", // for building the RAR
"templates":{ // default message templates
"*err": [
{"tag": "SessionId", "path": "*rep.Session-Id", "type": "*variable",
@@ -457,6 +458,26 @@ const CGRATES_CFG_JSON = `
"value": "~*req.User-Name", "mandatory": true},
{"tag": "OriginStateID", "path": "*diamreq.Origin-State-Id", "type": "*constant",
"value": "1"},
],
"*rar": [
{"tag": "SessionId", "path": "*diamreq.Session-Id", "type": "*variable",
"value": "~*req.Session-Id", "mandatory": true},
{"tag": "OriginHost", "path": "*diamreq.Origin-Host", "type": "*variable",
"value": "~*req.Destination-Host", "mandatory": true},
{"tag": "OriginRealm", "path": "*diamreq.Origin-Realm", "type": "*variable",
"value": "~*req.Destination-Realm", "mandatory": true},
{"tag": "DestinationRealm", "path": "*diamreq.Destination-Realm", "type": "*variable",
"value": "~*req.Origin-Realm", "mandatory": true},
{"tag": "DestinationHost", "path": "*diamreq.Destination-Host", "type": "*variable",
"value": "~*req.Origin-Host", "mandatory": true},
{"tag": "AuthApplicationId", "path": "*diamreq.Auth-Application-Id", "type": "*variable",
"value": "~*vars.*appid", "mandatory": true},
{"tag": "UserName", "path": "*diamreq.User-Name", "type": "*variable",
"value": "~*req.User-Name", "mandatory": true},
{"tag": "OriginStateID", "path": "*diamreq.Origin-State-Id", "type": "*constant",
"value": "1"},
{"tag": "ReAuthRequestType", "path": "*diamreq.Re-Auth-Request-Type", "type": "*constant",
"value": "0"},
]
},
"request_processors": [ // list of processors to be applied to diameter messages

View File

@@ -756,6 +756,7 @@ func TestDiameterAgentJsonCfg(t *testing.T) {
Concurrent_requests: utils.IntPointer(-1),
Synced_conn_requests: utils.BoolPointer(false),
Asr_template: utils.StringPointer(""),
Rar_template: utils.StringPointer(""),
Templates: map[string][]*FcTemplateJsonCfg{
utils.MetaErr: {
{
@@ -869,13 +870,67 @@ func TestDiameterAgentJsonCfg(t *testing.T) {
Type: utils.StringPointer(utils.META_CONSTANT),
Value: utils.StringPointer("1")},
},
utils.MetaRAR: {
{
Tag: utils.StringPointer("SessionId"),
Path: utils.StringPointer(fmt.Sprintf("%s.Session-Id", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.Session-Id"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("OriginHost"),
Path: utils.StringPointer(fmt.Sprintf("%s.Origin-Host", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.Destination-Host"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("OriginRealm"),
Path: utils.StringPointer(fmt.Sprintf("%s.Origin-Realm", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.Destination-Realm"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("DestinationRealm"),
Path: utils.StringPointer(fmt.Sprintf("%s.Destination-Realm", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.Origin-Realm"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("DestinationHost"),
Path: utils.StringPointer(fmt.Sprintf("%s.Destination-Host", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.Origin-Host"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("AuthApplicationId"),
Path: utils.StringPointer(fmt.Sprintf("%s.Auth-Application-Id", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*vars.*appid"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("UserName"),
Path: utils.StringPointer(fmt.Sprintf("%s.User-Name", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.MetaVariable),
Value: utils.StringPointer("~*req.User-Name"),
Mandatory: utils.BoolPointer(true)},
{
Tag: utils.StringPointer("OriginStateID"),
Path: utils.StringPointer(fmt.Sprintf("%s.Origin-State-Id", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.META_CONSTANT),
Value: utils.StringPointer("1")},
{
Tag: utils.StringPointer("ReAuthRequestType"),
Path: utils.StringPointer(fmt.Sprintf("%s.Re-Auth-Request-Type", utils.MetaDiamreq)),
Type: utils.StringPointer(utils.META_CONSTANT),
Value: utils.StringPointer("0")},
},
},
Request_processors: &[]*ReqProcessorJsnCfg{},
}
if cfg, err := dfCgrJsonCfg.DiameterAgentJsonCfg(); err != nil {
t.Error(err)
} else if !reflect.DeepEqual(eCfg, cfg) {
t.Errorf("expecting: %s, \n\nreceived: %s", utils.ToIJSON(eCfg), utils.ToIJSON(cfg))
t.Errorf("expecting: %s, \n\nreceived: %s", utils.ToJSON(eCfg), utils.ToJSON(cfg))
}
}

View File

@@ -33,6 +33,7 @@ type DiameterAgentCfg struct {
ConcurrentReqs int // limit the maximum number of requests processed
SyncedConnReqs bool
ASRTemplate string
RARTemplate string
Templates map[string][]*FCTemplate
RequestProcessors []*RequestProcessor
}
@@ -85,6 +86,9 @@ func (da *DiameterAgentCfg) loadFromJsonCfg(jsnCfg *DiameterAgentJsonCfg, separa
if jsnCfg.Asr_template != nil {
da.ASRTemplate = *jsnCfg.Asr_template
}
if jsnCfg.Rar_template != nil {
da.RARTemplate = *jsnCfg.Rar_template
}
if jsnCfg.Templates != nil {
if da.Templates == nil {
da.Templates = make(map[string][]*FCTemplate)

View File

@@ -313,6 +313,7 @@ type DiameterAgentJsonCfg struct {
Concurrent_requests *int
Synced_conn_requests *bool
Asr_template *string
Rar_template *string
Templates map[string][]*FcTemplateJsonCfg
Request_processors *[]*ReqProcessorJsnCfg
}

View File

@@ -44,6 +44,7 @@ type BiRPClient interface {
Call(serviceMethod string, args interface{}, reply interface{}) error
V1DisconnectSession(args utils.AttrDisconnectSession, reply *string) (err error)
V1GetActiveSessionIDs(ignParam string, sessionIDs *[]*SessionID) (err error)
V1SendRAR(originID string, reply *string) (err error)
}
// getSessionTTL retrieves SessionTTL setting out of ev

View File

@@ -3613,3 +3613,50 @@ func (sS *SessionS) BiRPCV1ProcessCDR(clnt rpcclient.ClientConnector,
Event: ev}},
rply)
}
func (sS *SessionS) sendRar(s *Session) (err error) {
clnt := sS.biJClnt(s.ClientConnID)
if clnt == nil {
return fmt.Errorf("calling %s requires bidirectional JSON connection, connID: <%s>",
utils.SessionSv1SendRAR, s.ClientConnID)
}
var originID string
if originID, err = s.EventStart.GetString(utils.OriginID); err != nil {
return
}
var rply string
if err = clnt.conn.Call(utils.SessionSv1SendRAR, originID, &rply); err == utils.ErrNotImplemented {
err = nil
}
return
}
// BiRPCv1SendRAR sends a RAR for sessions matching sessions
func (sS *SessionS) BiRPCv1SendRAR(clnt rpcclient.ClientConnector,
args *utils.SessionFilter, reply *string) (err error) {
if args == nil { //protection in case on nil
args = &utils.SessionFilter{}
}
aSs := sS.filterSessions(args, false)
if len(aSs) == 0 {
return utils.ErrNotFound
}
for _, as := range aSs {
ss := sS.getSessions(as.CGRID, false)
if len(ss) == 0 {
continue
}
if errTerm := sS.sendRar(ss[0]); errTerm != nil {
utils.Logger.Warning(
fmt.Sprintf(
"<%s> failed sending RAR for session with id: <%s>, err: <%s>",
utils.SessionS, ss[0].cgrID(), errTerm.Error()))
err = utils.ErrPartiallyExecuted
}
}
if err != nil {
return
}
*reply = utils.OK
return
}

View File

@@ -750,6 +750,7 @@ const (
MetaSum = "*sum"
MetaAverage = "*average"
MetaDistinct = "*distinct"
MetaRAR = "*rar"
)
// Services
@@ -1355,6 +1356,7 @@ const (
SessionSv1ActivateSessions = "SessionSv1.ActivateSessions"
SessionSv1DeactivateSessions = "SessionSv1.DeactivateSessions"
SMGenericV1InitiateSession = "SMGenericV1.InitiateSession"
SessionSv1SendRAR = "SessionSv1.SendRAR"
)
// Responder APIs