AgentRequest.setCGRReply implementation, DNSAgent with one supplier

This commit is contained in:
DanB
2019-06-05 20:52:30 +02:00
parent 0ce0ecb523
commit 134ffc7a0a
15 changed files with 200 additions and 144 deletions

View File

@@ -33,10 +33,14 @@ import (
func newAgentRequest(req config.DataProvider,
vars map[string]interface{},
cgrRply *config.NavigableMap,
rply *config.NavigableMap,
tntTpl config.RSRParsers,
dfltTenant, timezone string,
filterS *engine.FilterS) (ar *AgentRequest) {
if cgrRply == nil {
cgrRply = config.NewNavigableMap(nil)
}
if rply == nil {
rply = config.NewNavigableMap(nil)
}
@@ -44,7 +48,7 @@ func newAgentRequest(req config.DataProvider,
Request: req,
Vars: config.NewNavigableMap(vars),
CGRRequest: config.NewNavigableMap(nil),
CGRReply: config.NewNavigableMap(nil),
CGRReply: cgrRply,
Reply: rply,
timezone: timezone,
filterS: filterS,
@@ -182,6 +186,8 @@ func (aReq *AgentRequest) ParseField(
switch cfgFld.Type {
default:
return "", fmt.Errorf("unsupported type: <%s>", cfgFld.Type)
case utils.META_NONE:
return
case utils.META_FILLER:
out, err = cfgFld.Value.ParseValue(utils.EmptyString)
cfgFld.Padding = "right"
@@ -310,3 +316,23 @@ func (aReq *AgentRequest) ParseField(
}
return
}
// setCGRReply will set the aReq.cgrReply based on reply coming from upstream or error
// returns error in case of reply not converting to NavigableMap
func (aReq *AgentRequest) setCGRReply(rply config.NavigableMapper, errRply error) (err error) {
var nm *config.NavigableMap
if errRply != nil {
nm = config.NewNavigableMap(map[string]interface{}{
utils.Error: errRply.Error()})
} else {
nm = config.NewNavigableMap(nil)
if rply != nil {
if nm, err = rply.AsNavigableMap(nil); err != nil {
return
}
}
nm.Set([]string{utils.Error}, "", false, false) // enforce empty error
}
*aReq.CGRReply = *nm // update value so we can share CGRReply
return
}

View File

@@ -41,7 +41,7 @@ func TestAgReqAsNavigableMap(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.CGRID},
utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()),
@@ -137,7 +137,7 @@ func TestAgReqMaxCost(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.CapMaxUsage}, "120s", false, false)
@@ -182,7 +182,7 @@ func TestAgReqParseFieldDiameter(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
//pass the data provider to agent request
agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(dP, nil, nil, nil, nil, "cgrates.org", "", filterS)
tplFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "MandatoryFalse",
@@ -232,7 +232,7 @@ func TestAgReqParseFieldRadius(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
//pass the data provider to agent request
agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(dP, nil, nil, nil, nil, "cgrates.org", "", filterS)
tplFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "MandatoryFalse",
FieldId: "MandatoryFalse", Type: utils.META_COMPOSED,
@@ -272,7 +272,7 @@ Host: api.cgrates.org
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
//pass the data provider to agent request
agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(dP, nil, nil, nil, nil, "cgrates.org", "", filterS)
tplFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "MandatoryFalse",
FieldId: "MandatoryFalse", Type: utils.META_COMPOSED,
@@ -343,7 +343,7 @@ func TestAgReqParseFieldHttpXml(t *testing.T) {
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
//pass the data provider to agent request
agReq := newAgentRequest(dP, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(dP, nil, nil, nil, nil, "cgrates.org", "", filterS)
tplFlds := []*config.FCTemplate{
&config.FCTemplate{Tag: "MandatoryFalse",
FieldId: "MandatoryFalse", Type: utils.META_COMPOSED,
@@ -371,7 +371,7 @@ func TestAgReqEmptyFilter(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.CGRID},
utils.Sha1("dsafdsaf", time.Date(2013, 11, 7, 8, 42, 26, 0, time.UTC).String()),
@@ -414,7 +414,7 @@ func TestAgReqMetaExponent(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq.CGRRequest.Set([]string{"Value"}, "2", false, false)
agReq.CGRRequest.Set([]string{"Exponent"}, "2", false, false)
@@ -440,7 +440,7 @@ func TestAgReqCGRActiveRequest(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
tplFlds := []*config.FCTemplate{
@@ -483,7 +483,7 @@ func TestAgReqFieldAsNone(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false)
agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false)
@@ -520,7 +520,7 @@ func TestAgReqFieldAsNone2(t *testing.T) {
dm := engine.NewDataManager(data)
cfg, _ := config.NewDefaultCGRConfig()
filterS := engine.NewFilterS(cfg, nil, nil, dm)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", filterS)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", filterS)
// populate request, emulating the way will be done in HTTPAgent
agReq.CGRRequest.Set([]string{utils.ToR}, utils.VOICE, false, false)
agReq.CGRRequest.Set([]string{utils.Account}, "1001", false, false)

View File

@@ -200,6 +200,7 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
da.aReqsLck.Unlock()
}()
}
cgrRplyNM := config.NewNavigableMap(nil)
rply := config.NewNavigableMap(nil) // share it among different processors
var processed bool
for _, reqProcessor := range da.cgrCfg.DiameterAgentCfg().RequestProcessors {
@@ -207,7 +208,7 @@ func (da *DiameterAgent) handleMessage(c diam.Conn, m *diam.Message) {
lclProcessed, err = da.processRequest(
reqProcessor,
newAgentRequest(
diamDP, reqVars, rply,
diamDP, reqVars, cgrRplyNM, rply,
reqProcessor.Tenant, da.cgrCfg.GeneralCfg().DefaultTenant,
utils.FirstNonEmpty(reqProcessor.Timezone,
da.cgrCfg.GeneralCfg().DefaultTimezone),
@@ -290,10 +291,10 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var authReply sessions.V1AuthorizeReply
rply := new(sessions.V1AuthorizeReply)
err = da.sS.Call(utils.SessionSv1AuthorizeEvent,
authArgs, &authReply)
if agReq.CGRReply, err = NewCGRReply(&authReply, err); err != nil {
authArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaInitiate:
@@ -304,10 +305,10 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var initReply sessions.V1InitSessionReply
rply := new(sessions.V1InitSessionReply)
err = da.sS.Call(utils.SessionSv1InitiateSession,
initArgs, &initReply)
if agReq.CGRReply, err = NewCGRReply(&initReply, err); err != nil {
initArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaUpdate:
@@ -315,10 +316,10 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaAttributes),
reqProcessor.Flags.HasKey(utils.MetaAccounts),
cgrEv, cgrArgs.ArgDispatcher)
var updateReply sessions.V1UpdateSessionReply
rply := new(sessions.V1UpdateSessionReply)
err = da.sS.Call(utils.SessionSv1UpdateSession,
updateArgs, &updateReply)
if agReq.CGRReply, err = NewCGRReply(&updateReply, err); err != nil {
updateArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaTerminate:
@@ -328,10 +329,10 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var tRply string
rply := utils.StringPointer("")
err = da.sS.Call(utils.SessionSv1TerminateSession,
terminateArgs, &tRply)
if agReq.CGRReply, err = NewCGRReply(nil, err); err != nil {
terminateArgs, rply)
if err = agReq.setCGRReply(nil, err); err != nil {
return
}
case utils.MetaEvent:
@@ -345,15 +346,15 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var eventRply sessions.V1ProcessEventReply
rply := new(sessions.V1ProcessEventReply)
err = da.sS.Call(utils.SessionSv1ProcessEvent,
evArgs, &eventRply)
evArgs, rply)
if utils.ErrHasPrefix(err, utils.RalsErrorPrfx) {
cgrEv.Event[utils.Usage] = 0 // avoid further debits
} else if eventRply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *eventRply.MaxUsage // make sure the CDR reflects the debit
} else if rply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *rply.MaxUsage // make sure the CDR reflects the debit
}
if agReq.CGRReply, err = NewCGRReply(&eventRply, err); err != nil {
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaCDRs: // allow CDR processing
@@ -361,10 +362,10 @@ func (da *DiameterAgent) processRequest(reqProcessor *config.RequestProcessor,
// separate request so we can capture the Terminate/Event also here
if reqProcessor.Flags.HasKey(utils.MetaCDRs) &&
!reqProcessor.Flags.HasKey(utils.MetaDryRun) {
var rplyCDRs string
rplyCDRs := utils.StringPointer("")
if err = da.sS.Call(utils.SessionSv1ProcessCDR,
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv,
ArgDispatcher: cgrArgs.ArgDispatcher}, &rplyCDRs); err != nil {
ArgDispatcher: cgrArgs.ArgDispatcher}, rplyCDRs); err != nil {
agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false)
}
}
@@ -410,7 +411,10 @@ func (da *DiameterAgent) V1DisconnectSession(args utils.AttrDisconnectSession, r
dmd := msg.(*diamMsgData)
aReq := newAgentRequest(
newDADataProvider(dmd.c, dmd.m),
dmd.vars, nil, nil,
dmd.vars,
config.NewNavigableMap(nil),
config.NewNavigableMap(nil),
nil,
da.cgrCfg.GeneralCfg().DefaultTenant,
da.cgrCfg.GeneralCfg().DefaultTimezone, da.filterS)
nM, err := aReq.AsNavigableMap(da.cgrCfg.DiameterAgentCfg().Templates[da.cgrCfg.DiameterAgentCfg().ASRTemplate])

View File

@@ -91,6 +91,7 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) {
}
reqVars[E164Address] = e164
}
cgrRplyNM := config.NewNavigableMap(nil)
rplyNM := config.NewNavigableMap(nil) // share it among different processors
var processed bool
var err error
@@ -99,7 +100,7 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) {
lclProcessed, err = da.processRequest(
reqProcessor,
newAgentRequest(
dnsDP, reqVars, rplyNM,
dnsDP, reqVars, cgrRplyNM, rplyNM,
reqProcessor.Tenant,
da.cgrCfg.GeneralCfg().DefaultTenant,
utils.FirstNonEmpty(da.cgrCfg.DNSAgentCfg().Timezone,
@@ -134,6 +135,7 @@ func (da *DNSAgent) handleMessage(w dns.ResponseWriter, req *dns.Msg) {
utils.DNSAgent, err.Error(), utils.ToJSON(rply), utils.ToJSON(rplyNM)))
rply.Rcode = dns.RcodeServerFailure
dnsWriteMsg(w, rply)
return
}
if err = dnsWriteMsg(w, rply); err != nil { // failed sending, most probably content issue
rply = new(dns.Msg)
@@ -190,10 +192,10 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var authReply sessions.V1AuthorizeReply
rply := new(sessions.V1AuthorizeReply)
err = da.sS.Call(utils.SessionSv1AuthorizeEvent,
authArgs, &authReply)
if agReq.CGRReply, err = NewCGRReply(&authReply, err); err != nil {
authArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaInitiate:
@@ -204,10 +206,10 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var initReply sessions.V1InitSessionReply
rply := new(sessions.V1InitSessionReply)
err = da.sS.Call(utils.SessionSv1InitiateSession,
initArgs, &initReply)
if agReq.CGRReply, err = NewCGRReply(&initReply, err); err != nil {
initArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaUpdate:
@@ -215,10 +217,10 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaAttributes),
reqProcessor.Flags.HasKey(utils.MetaAccounts),
cgrEv, cgrArgs.ArgDispatcher)
var updateReply sessions.V1UpdateSessionReply
rply := new(sessions.V1UpdateSessionReply)
err = da.sS.Call(utils.SessionSv1UpdateSession,
updateArgs, &updateReply)
if agReq.CGRReply, err = NewCGRReply(&updateReply, err); err != nil {
updateArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaTerminate:
@@ -228,10 +230,10 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var tRply string
rply := utils.StringPointer("")
err = da.sS.Call(utils.SessionSv1TerminateSession,
terminateArgs, &tRply)
if agReq.CGRReply, err = NewCGRReply(nil, err); err != nil {
terminateArgs, rply)
if err = agReq.setCGRReply(nil, err); err != nil {
return
}
case utils.MetaEvent:
@@ -245,15 +247,15 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var eventRply sessions.V1ProcessEventReply
rply := new(sessions.V1ProcessEventReply) // need it so rpcclient can clone
err = da.sS.Call(utils.SessionSv1ProcessEvent,
evArgs, &eventRply)
evArgs, rply)
if utils.ErrHasPrefix(err, utils.RalsErrorPrfx) {
cgrEv.Event[utils.Usage] = 0 // avoid further debits
} else if eventRply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *eventRply.MaxUsage // make sure the CDR reflects the debit
} else if rply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *rply.MaxUsage // make sure the CDR reflects the debit
}
if agReq.CGRReply, err = NewCGRReply(&eventRply, err); err != nil {
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaCDRs: // allow CDR processing
@@ -261,7 +263,7 @@ func (da *DNSAgent) processRequest(reqProcessor *config.RequestProcessor,
// separate request so we can capture the Terminate/Event also here
if reqProcessor.Flags.HasKey(utils.MetaCDRs) &&
!reqProcessor.Flags.HasKey(utils.MetaDryRun) {
var rplyCDRs string
rplyCDRs := utils.StringPointer("")
if err = da.sS.Call(utils.SessionSv1ProcessCDR,
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv,
ArgDispatcher: cgrArgs.ArgDispatcher}, &rplyCDRs); err != nil {

View File

@@ -42,12 +42,12 @@ var (
var sTestsDNS = []func(t *testing.T){
testDNSitResetDB,
testDNSitStartEngine,
//testDNSitStartEngine,
testDNSitApierRpcConn,
testDNSitTPFromFolder,
testDNSitClntConn,
testDNSitClntNAPTRDryRun,
testDNSitClntNAPTRAttributes,
//testDNSitClntNAPTRDryRun,
//testDNSitClntNAPTRAttributes,
testDNSitClntNAPTRSuppliers,
testDNSitStopEngine,
}
@@ -165,8 +165,8 @@ func testDNSitClntNAPTRAttributes(t *testing.T) {
if answr.Order != 100 {
t.Errorf("received: <%q>", answr.Order)
}
if answr.Replacement != "sip:1\\@172.16.1.1." {
t.Errorf("Expected :<%q> , received: <%q>", "sip:1\\@172.16.1.1.", answr.Replacement)
if answr.Regexp != "sip:1\\@172.16.1.1." {
t.Errorf("Expected :<%q> , received: <%q>", "sip:1\\@172.16.1.1.", answr.Regexp)
}
}
}
@@ -185,10 +185,10 @@ func testDNSitClntNAPTRSuppliers(t *testing.T) {
}
answr := rply.Answer[0].(*dns.NAPTR)
if answr.Order != 100 {
t.Errorf("received: <%q>", answr.Order)
t.Errorf("received: <%v>", answr.Order)
}
if answr.Replacement != "sip:1\\@172.16.1.10." {
t.Errorf("received: <%q>", answr.Replacement)
if answr.Regexp != "!^(.*)$!sip:1@172.16.1.11!" {
t.Errorf("received: <%q>", answr.Regexp)
}
}
}

View File

@@ -58,8 +58,10 @@ func (ha *HTTPAgent) ServeHTTP(w http.ResponseWriter, req *http.Request) {
utils.HTTPAgent, err.Error()))
return
}
cgrRplyNM := config.NewNavigableMap(nil)
rplyNM := config.NewNavigableMap(nil)
for _, reqProcessor := range ha.reqProcessors {
agReq := newAgentRequest(dcdr, nil, nil,
agReq := newAgentRequest(dcdr, nil, cgrRplyNM, rplyNM,
reqProcessor.Tenant, ha.dfltTenant,
utils.FirstNonEmpty(reqProcessor.Timezone,
config.CgrConfig().GeneralCfg().DefaultTimezone),
@@ -139,10 +141,10 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var authReply sessions.V1AuthorizeReply
rply := new(sessions.V1AuthorizeReply)
err = ha.sessionS.Call(utils.SessionSv1AuthorizeEvent,
authArgs, &authReply)
if agReq.CGRReply, err = NewCGRReply(&authReply, err); err != nil {
authArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaInitiate:
@@ -153,10 +155,10 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var initReply sessions.V1InitSessionReply
rply := new(sessions.V1InitSessionReply)
err = ha.sessionS.Call(utils.SessionSv1InitiateSession,
initArgs, &initReply)
if agReq.CGRReply, err = NewCGRReply(&initReply, err); err != nil {
initArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaUpdate:
@@ -164,10 +166,10 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaAttributes),
reqProcessor.Flags.HasKey(utils.MetaAccounts),
cgrEv, cgrArgs.ArgDispatcher)
var updateReply sessions.V1UpdateSessionReply
rply := new(sessions.V1UpdateSessionReply)
err = ha.sessionS.Call(utils.SessionSv1UpdateSession,
updateArgs, &updateReply)
if agReq.CGRReply, err = NewCGRReply(&updateReply, err); err != nil {
updateArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaTerminate:
@@ -177,10 +179,10 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var tRply string
rply := utils.StringPointer("")
err = ha.sessionS.Call(utils.SessionSv1TerminateSession,
terminateArgs, &tRply)
if agReq.CGRReply, err = NewCGRReply(nil, err); err != nil {
terminateArgs, rply)
if err = agReq.setCGRReply(nil, err); err != nil {
return
}
case utils.MetaEvent:
@@ -194,15 +196,15 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var eventRply sessions.V1ProcessEventReply
rply := new(sessions.V1ProcessEventReply)
err = ha.sessionS.Call(utils.SessionSv1ProcessEvent,
evArgs, &eventRply)
evArgs, rply)
if utils.ErrHasPrefix(err, utils.RalsErrorPrfx) {
cgrEv.Event[utils.Usage] = 0 // avoid further debits
} else if eventRply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *eventRply.MaxUsage // make sure the CDR reflects the debit
} else if rply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *rply.MaxUsage // make sure the CDR reflects the debit
}
if agReq.CGRReply, err = NewCGRReply(&eventRply, err); err != nil {
if err = agReq.setCGRReply(nil, err); err != nil {
return
}
case utils.MetaCDRs: // allow CDR processing
@@ -210,9 +212,11 @@ func (ha *HTTPAgent) processRequest(reqProcessor *config.RequestProcessor,
// separate request so we can capture the Terminate/Event also here
if reqProcessor.Flags.HasKey(utils.MetaCDRs) &&
!reqProcessor.Flags.HasKey(utils.MetaDryRun) {
var rplyCDRs string
rplyCDRs := utils.StringPointer("")
if err = ha.sessionS.Call(utils.SessionSv1ProcessCDR,
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, &rplyCDRs); err != nil {
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv,
ArgDispatcher: cgrArgs.ArgDispatcher},
rplyCDRs); err != nil {
agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false)
}
}

View File

@@ -484,6 +484,7 @@ func diamErr(m *diam.Message, resCode uint32,
aReq := newAgentRequest(
newDADataProvider(nil, m), reqVars,
config.NewNavigableMap(nil),
config.NewNavigableMap(nil),
nil, tnt, tmz, filterS)
var rplyData *config.NavigableMap
if rplyData, err = aReq.AsNavigableMap(tpl); err != nil {

View File

@@ -117,24 +117,6 @@ func radReplyAppendAttributes(reply *radigo.Packet, agReq *AgentRequest,
return
}
// NewCGRReply is specific to replies coming from CGRateS
func NewCGRReply(rply config.NavigableMapper,
errRply error) (mp *config.NavigableMap, err error) {
if errRply != nil {
return config.NewNavigableMap(map[string]interface{}{
utils.Error: errRply.Error()}), nil
}
mp = config.NewNavigableMap(nil)
if rply != nil {
mp, err = rply.AsNavigableMap(nil)
if err != nil {
return nil, err
}
}
mp.Set([]string{utils.Error}, "", false, false) // enforce empty error
return
}
// newRADataProvider constructs a DataProvider
func newRADataProvider(req *radigo.Packet) (dP config.DataProvider) {
dP = &radiusDP{req: req, cache: config.NewNavigableMap(nil)}

View File

@@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
package agents
import (
"errors"
"fmt"
"reflect"
"strings"
@@ -97,7 +96,7 @@ func TestRadComposedFieldValue(t *testing.T) {
if err := pkt.AddAVPWithName("Cisco-NAS-Port", "CGR1", "Cisco"); err != nil {
t.Error(err)
}
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", nil)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", nil)
agReq.Vars.Set([]string{MetaRadReqType}, MetaRadAcctStart, false, false)
agReq.Vars.Set([]string{"Cisco"}, "CGR1", false, false)
agReq.Vars.Set([]string{"User-Name"}, "flopsy", false, false)
@@ -117,11 +116,10 @@ func TestRadFieldOutVal(t *testing.T) {
t.Error(err)
}
eOut := fmt.Sprintf("%s|flopsy|CGR1", MetaRadAcctStart)
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", nil)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", nil)
agReq.Vars.Set([]string{MetaRadReqType}, MetaRadAcctStart, false, false)
agReq.Vars.Set([]string{"Cisco"}, "CGR1", false, false)
agReq.Vars.Set([]string{"User-Name"}, "flopsy", false, false)
//processorVars{MetaRadReqType: MetaRadAcctStart}
cfgFld := &config.FCTemplate{Tag: "ComposedTest", Type: utils.META_COMPOSED, FieldId: utils.Destination,
Value: config.NewRSRParsersMustCompile("~*vars.*radReqType;|;~*vars.User-Name;|;~*vars.Cisco", true, utils.INFIELD_SEP), Mandatory: true}
if outVal, err := radFieldOutVal(pkt, agReq, cfgFld); err != nil {
@@ -139,7 +137,7 @@ func TestRadReplyAppendAttributes(t *testing.T) {
&config.FCTemplate{Tag: "Acct-Session-Time", FieldId: "Acct-Session-Time", Type: utils.META_COMPOSED,
Value: config.NewRSRParsersMustCompile("~*cgrep.MaxUsage{*duration_seconds}", true, utils.INFIELD_SEP)},
}
agReq := newAgentRequest(nil, nil, nil, nil, "cgrates.org", "", nil)
agReq := newAgentRequest(nil, nil, nil, nil, nil, "cgrates.org", "", nil)
agReq.CGRReply.Set([]string{utils.CapMaxUsage}, time.Duration(time.Hour), false, false)
agReq.CGRReply.Set([]string{utils.CapAttributes, "RadReply"}, "AccessAccept", false, false)
agReq.CGRReply.Set([]string{utils.CapAttributes, utils.Account}, "1001", false, false)
@@ -162,6 +160,7 @@ func (ev myEv) AsNavigableMap(tpl []*config.FCTemplate) (*config.NavigableMap, e
return config.NewNavigableMap(ev), nil
}
/*
func TestNewCGRReply(t *testing.T) {
eCgrRply := config.NewNavigableMap(map[string]interface{}{
utils.Error: "some",
@@ -187,6 +186,7 @@ func TestNewCGRReply(t *testing.T) {
t.Errorf("Expecting: %+v, received: %+v", eCgrRply, rpl)
}
}
*/
func TestRadiusDPFieldAsInterface(t *testing.T) {
pkt := radigo.NewPacket(radigo.AccountingRequest, 1, dictRad, coder, "CGRateS.org")

View File

@@ -75,9 +75,11 @@ func (ra *RadiusAgent) handleAuth(req *radigo.Packet) (rpl *radigo.Packet, err e
dcdr := newRADataProvider(req) // dcdr will provide information from request
rpl = req.Reply()
rpl.Code = radigo.AccessAccept
cgrRplyNM := config.NewNavigableMap(nil)
rplyNM := config.NewNavigableMap(nil)
var processed bool
for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors {
agReq := newAgentRequest(dcdr, nil, nil,
agReq := newAgentRequest(dcdr, nil, cgrRplyNM, rplyNM,
reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant,
utils.FirstNonEmpty(reqProcessor.Timezone,
config.CgrConfig().GeneralCfg().DefaultTimezone),
@@ -110,9 +112,11 @@ func (ra *RadiusAgent) handleAcct(req *radigo.Packet) (rpl *radigo.Packet, err e
dcdr := newRADataProvider(req) // dcdr will provide information from request
rpl = req.Reply()
rpl.Code = radigo.AccountingResponse
cgrRplyNM := config.NewNavigableMap(nil)
rplyNM := config.NewNavigableMap(nil)
var processed bool
for _, reqProcessor := range ra.cgrCfg.RadiusAgentCfg().RequestProcessors {
agReq := newAgentRequest(dcdr, nil, nil,
agReq := newAgentRequest(dcdr, nil, cgrRplyNM, rplyNM,
reqProcessor.Tenant, ra.cgrCfg.GeneralCfg().DefaultTenant,
utils.FirstNonEmpty(reqProcessor.Timezone,
config.CgrConfig().GeneralCfg().DefaultTimezone),
@@ -183,10 +187,10 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var authReply sessions.V1AuthorizeReply
rply := new(sessions.V1AuthorizeReply)
err = ra.sessionS.Call(utils.SessionSv1AuthorizeEvent,
authArgs, &authReply)
if agReq.CGRReply, err = NewCGRReply(&authReply, err); err != nil {
authArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaInitiate:
@@ -197,10 +201,10 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var initReply sessions.V1InitSessionReply
rply := new(sessions.V1InitSessionReply)
err = ra.sessionS.Call(utils.SessionSv1InitiateSession,
initArgs, &initReply)
if agReq.CGRReply, err = NewCGRReply(&initReply, err); err != nil {
initArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaUpdate:
@@ -208,10 +212,10 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaAttributes),
reqProcessor.Flags.HasKey(utils.MetaAccounts),
cgrEv, cgrArgs.ArgDispatcher)
var updateReply sessions.V1UpdateSessionReply
rply := new(sessions.V1UpdateSessionReply)
err = ra.sessionS.Call(utils.SessionSv1UpdateSession,
updateArgs, &updateReply)
if agReq.CGRReply, err = NewCGRReply(&updateReply, err); err != nil {
updateArgs, rply)
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaTerminate:
@@ -221,10 +225,10 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaThresholds),
reqProcessor.Flags.HasKey(utils.MetaStats),
cgrEv, cgrArgs.ArgDispatcher)
var tRply string
rply := utils.StringPointer("")
err = ra.sessionS.Call(utils.SessionSv1TerminateSession,
terminateArgs, &tRply)
if agReq.CGRReply, err = NewCGRReply(nil, err); err != nil {
terminateArgs, rply)
if err = agReq.setCGRReply(nil, err); err != nil {
return
}
case utils.MetaEvent:
@@ -238,24 +242,25 @@ func (ra *RadiusAgent) processRequest(reqProcessor *config.RequestProcessor,
reqProcessor.Flags.HasKey(utils.MetaSuppliersIgnoreErrors),
reqProcessor.Flags.HasKey(utils.MetaSuppliersEventCost),
cgrEv, cgrArgs.ArgDispatcher, *cgrArgs.SupplierPaginator)
var eventRply sessions.V1ProcessEventReply
err = ra.sessionS.Call(utils.SessionSv1ProcessEvent,
evArgs, &eventRply)
rply := new(sessions.V1ProcessEventReply)
err = ra.sessionS.Call(utils.SessionSv1ProcessEvent, evArgs, rply)
if utils.ErrHasPrefix(err, utils.RalsErrorPrfx) {
cgrEv.Event[utils.Usage] = 0 // avoid further debits
} else if eventRply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *eventRply.MaxUsage // make sure the CDR reflects the debit
} else if rply.MaxUsage != nil {
cgrEv.Event[utils.Usage] = *rply.MaxUsage // make sure the CDR reflects the debit
}
if agReq.CGRReply, err = NewCGRReply(&eventRply, err); err != nil {
if err = agReq.setCGRReply(rply, err); err != nil {
return
}
case utils.MetaCDRs: // allow this method
}
// separate request so we can capture the Terminate/Event also here
if reqProcessor.Flags.HasKey(utils.MetaCDRs) {
var rplyCDRs string
rplyCDRs := utils.StringPointer("")
if err = ra.sessionS.Call(utils.SessionSv1ProcessCDR,
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv, ArgDispatcher: cgrArgs.ArgDispatcher}, &rplyCDRs); err != nil {
&utils.CGREventWithArgDispatcher{CGREvent: cgrEv,
ArgDispatcher: cgrArgs.ArgDispatcher},
rplyCDRs); err != nil {
agReq.CGRReply.Set([]string{utils.Error}, err.Error(), false, false)
}
}

View File

@@ -59,7 +59,7 @@ type NavigableMap struct {
order [][]string // order of field paths
}
// Add will add items into NavigableMap populating also order
// Set will set items into NavigableMap populating also order
// apnd parameter allows appending the data if both sides are []*NMItem
func (nM *NavigableMap) Set(path []string, data interface{}, apnd, ordered bool) {
if ordered {

View File

@@ -21,9 +21,7 @@
"type": "*constant", "value": "U"},
{"tag": "NAPTRService", "field_id": "Service",
"type": "*constant", "value": "E2U+SIP"},
{"tag": "NAPTRRegexp", "field_id": "Regexp",
"type": "*constant", "value": "^.*$"},
{"tag": "NAPTRReplacement", "field_id": "Replacement",
{"tag": "NAPTRReplacement", "field_id": "Regexp",
"type": "*variable", "value": "~*cgrep.Attributes.NAPTRAddress"},
],
},

View File

@@ -3,12 +3,26 @@
"dns_agent": {
"request_processors": [
{
"id": "NAPTRSuppliers",
"filters": ["*string:~*vars.QueryType:NAPTR", "*string:~*vars.E164Address:4986517174965"],
"flags": ["*auth", "*suppliers"],
"id": "NAPTRSuppliersQuery",
"filters": ["*string:~*vars.QueryType:NAPTR",
"*string:~*vars.E164Address:4986517174965"],
"flags": ["*event", "*suppliers"],
"continue_on_success": true,
"request_fields":[
{"tag": "TOR", "field_id": "Account", "type": "*constant", "value": "1001"}, // so we can match the supplier profile
],
"reply_fields":[
{"tag": "DispatchReply", "type": "*none",
"blocker": true}, // enforces continue_on_success so we can check answer with filters
],
},
{
"id": "NAPTRSuppliersOneSupplier",
"filters": ["*string:~*vars.QueryType:NAPTR",
"*string:~*vars.E164Address:4986517174965",
"*gte:~*cgrep.Suppliers.Count:1"],
"flags": ["*none"], // do not send request to CGRateS
"continue_on_success": true,
"reply_fields":[
{"tag": "NAPTROrder", "field_id": "Order",
"type": "*constant", "value": "100"},
@@ -18,13 +32,31 @@
"type": "*constant", "value": "U"},
{"tag": "NAPTRService", "field_id": "Service",
"type": "*constant", "value": "E2U+SIP"},
{"tag": "NAPTRRegexp", "field_id": "Regexp",
"type": "*constant", "value": "^.*$"},
{"tag": "NAPTRReplacement", "field_id": "Replacement",
"type": "*constant", "value": "sip:\\1@172.16.1.10."},
{"tag": "NAPTRRegexp", "field_id": "Regexp", "type": "*variable",
"value": "~*cgrep.Suppliers.SortedSuppliers[0].SupplierParameters"},
],
},
{
"id": "NAPTRSuppliersTwoSuppliers",
"filters": ["*string:~*vars.QueryType:NAPTR",
"*string:~*vars.E164Address:4986517174965",
"*gte:~*cgrep.Suppliers.Count:2"],
"flags": ["*none"],
"continue_on_success": true,
"reply_fields":[
{"tag": "NAPTROrder", "type": "*constant", "new_branch": true,
"field_id": "Order", "value": "100"},
{"tag": "NAPTRPreference", "field_id": "Preference",
"type": "*constant", "value": "10"},
{"tag": "NAPTRFlags", "field_id": "Flags",
"type": "*constant", "value": "U"},
{"tag": "NAPTRService", "field_id": "Service",
"type": "*constant", "value": "E2U+SIP"},
{"tag": "NAPTRRegexp", "field_id": "Regexp", "type": "*variable",
"value": "~*cgrep.Suppliers.SortedSuppliers[1].SupplierParameters;!"},
],
},
],
},
}
}

View File

@@ -0,0 +1,4 @@
#Tenant,ID,FilterIDs,ActivationInterval,Sorting,SortingParamameters,SupplierID,SupplierFilterIDs,SupplierAccountIDs,SupplierRatingPlanIDs,SupplierResourceIDs,SupplierStatIDs,SupplierWeight,SupplierBlocker,SupplierParameters,Weight
cgrates.org,SPL_ACNT_1001,*string:~Account:1001,,*weight,,supplier1,,,,,,10,,!^(.*)$!sip:\1@172.16.1.11!,10
cgrates.org,SPL_ACNT_1001,,,,,supplier2,,,,,,5,,!^(.*)$!sip:\\1@172.16.1.12!,10
1 #Tenant ID FilterIDs ActivationInterval Sorting SortingParamameters SupplierID SupplierFilterIDs SupplierAccountIDs SupplierRatingPlanIDs SupplierResourceIDs SupplierStatIDs SupplierWeight SupplierBlocker SupplierParameters Weight
2 cgrates.org SPL_ACNT_1001 *string:~Account:1001 *weight supplier1 10 !^(.*)$!sip:\1@172.16.1.11! 10
3 cgrates.org SPL_ACNT_1001 supplier2 5 !^(.*)$!sip:\\1@172.16.1.12! 10

View File

@@ -318,19 +318,17 @@ func GreaterThan(item, oItem interface{}, orEqual bool) (gte bool, err error) {
typItem := reflect.TypeOf(item)
typOItem := reflect.TypeOf(oItem)
if typItem != typOItem {
if item, err = GetUniformType(item); err != nil {
return false, err
if item, err = GetUniformType(item); err == nil { // overwrite type only if possible
typItem = reflect.TypeOf(item)
}
if oItem, err = GetUniformType(oItem); err != nil {
return false, err
if oItem, err = GetUniformType(oItem); err == nil {
typOItem = reflect.TypeOf(oItem)
}
typItem = reflect.TypeOf(item)
typOItem = reflect.TypeOf(oItem)
}
if !typItem.Comparable() ||
!typOItem.Comparable() ||
typItem != typOItem {
return false, errors.New("incomparable")
return false, fmt.Errorf("incomparable: <%+v> with <%+v>", item, oItem)
}
switch tVal := item.(type) {
case float64: