diff --git a/agents/agentreq.go b/agents/agentreq.go index 85b4408a3..e330d4a85 100644 --- a/agents/agentreq.go +++ b/agents/agentreq.go @@ -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 +} diff --git a/agents/agentreq_test.go b/agents/agentreq_test.go index d64be2ea7..1736219a4 100644 --- a/agents/agentreq_test.go +++ b/agents/agentreq_test.go @@ -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) diff --git a/agents/diamagent.go b/agents/diamagent.go index b3d3cafca..cc092453c 100644 --- a/agents/diamagent.go +++ b/agents/diamagent.go @@ -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]) diff --git a/agents/dnsagent.go b/agents/dnsagent.go index 4487c08fe..5bf544ac9 100644 --- a/agents/dnsagent.go +++ b/agents/dnsagent.go @@ -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 { diff --git a/agents/dnsagent_it_test.go b/agents/dnsagent_it_test.go index ba54fd0a5..4a7090417 100644 --- a/agents/dnsagent_it_test.go +++ b/agents/dnsagent_it_test.go @@ -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) } } } diff --git a/agents/httpagent.go b/agents/httpagent.go index 51555ff9e..65c187b1b 100644 --- a/agents/httpagent.go +++ b/agents/httpagent.go @@ -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) } } diff --git a/agents/libdiam.go b/agents/libdiam.go index 871c12705..8de332a8f 100644 --- a/agents/libdiam.go +++ b/agents/libdiam.go @@ -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 { diff --git a/agents/librad.go b/agents/librad.go index e7ef2e304..925a21873 100644 --- a/agents/librad.go +++ b/agents/librad.go @@ -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)} diff --git a/agents/librad_test.go b/agents/librad_test.go index beaf992df..a6a761f74 100644 --- a/agents/librad_test.go +++ b/agents/librad_test.go @@ -19,7 +19,6 @@ along with this program. If not, see 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") diff --git a/agents/radagent.go b/agents/radagent.go index e95e46418..da25df321 100644 --- a/agents/radagent.go +++ b/agents/radagent.go @@ -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) } } diff --git a/config/navigablemap.go b/config/navigablemap.go index 73415016f..b0132d9b9 100644 --- a/config/navigablemap.go +++ b/config/navigablemap.go @@ -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 { diff --git a/data/conf/samples/dnsagent/attributes.json b/data/conf/samples/dnsagent/attributes.json index 92b2ebebd..4a7629a6c 100644 --- a/data/conf/samples/dnsagent/attributes.json +++ b/data/conf/samples/dnsagent/attributes.json @@ -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"}, ], }, diff --git a/data/conf/samples/dnsagent/suppliers.json b/data/conf/samples/dnsagent/suppliers.json index 01ca17393..d217a5fd1 100644 --- a/data/conf/samples/dnsagent/suppliers.json +++ b/data/conf/samples/dnsagent/suppliers.json @@ -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;!"}, ], }, ], }, -} \ No newline at end of file +} diff --git a/data/tariffplans/dnsagent/Suppliers.csv b/data/tariffplans/dnsagent/Suppliers.csv new file mode 100644 index 000000000..aa89e9fb5 --- /dev/null +++ b/data/tariffplans/dnsagent/Suppliers.csv @@ -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 + diff --git a/utils/reflect.go b/utils/reflect.go index a702eab94..5700b62eb 100644 --- a/utils/reflect.go +++ b/utils/reflect.go @@ -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: