// Converts itself into DiameterMessage func (self *CCA) AsDiameterMessage() (*diam.Message, error) { if _, err := self.diamMessage.NewAVP("Session-Id", avp.Mbit, 0, datatype.UTF8String(self.SessionId)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("Origin-Host", avp.Mbit, 0, datatype.DiameterIdentity(self.OriginHost)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("Origin-Realm", avp.Mbit, 0, datatype.DiameterIdentity(self.OriginRealm)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("Auth-Application-Id", avp.Mbit, 0, datatype.Unsigned32(self.AuthApplicationId)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("CC-Request-Type", avp.Mbit, 0, datatype.Enumerated(self.CCRequestType)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("CC-Request-Number", avp.Mbit, 0, datatype.Enumerated(self.CCRequestNumber)); err != nil { return nil, err } if _, err := self.diamMessage.NewAVP(avp.ResultCode, avp.Mbit, 0, datatype.Unsigned32(self.ResultCode)); err != nil { return nil, err } ccTimeAvp, err := self.diamMessage.Dictionary().FindAVP(self.diamMessage.Header.ApplicationID, "CC-Time") if err != nil { return nil, err } if _, err := self.diamMessage.NewAVP("Granted-Service-Unit", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(ccTimeAvp.Code, avp.Mbit, 0, datatype.Unsigned32(self.GrantedServiceUnit.CCTime))}}); err != nil { return nil, err } return self.diamMessage, nil }
func TestDmtAgentDryRun1(t *testing.T) { if !*testIntegration { return } ccr := diam.NewRequest(diam.CreditControl, 4, nil) ccr.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String("cgrates;1451911932;00082")) ccr.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity("CGR-DA")) ccr.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity("cgrates.org")) ccr.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)) ccr.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.UTF8String("pubsub1")) // Match specific DryRun profile ccr.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(4)) ccr.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(0)) ccr.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Time(time.Date(2016, 1, 5, 11, 30, 10, 0, time.UTC))) if _, err := ccr.NewAVP("Framed-IP-Address", avp.Mbit, 0, datatype.UTF8String("10.228.16.4")); err != nil { t.Error(err) } if err := dmtClient.SendMessage(ccr); err != nil { t.Error(err) } time.Sleep(time.Duration(100) * time.Millisecond) msg := dmtClient.ReceivedMessage() if msg == nil { t.Fatal("No message returned") } if avps, err := msg.FindAVPsWithPath([]interface{}{"Result-Code"}, dict.UndefinedVendorID); err != nil { t.Error(err) } else if len(avps) == 0 { t.Error("Result-Code") } else if strResult := avpValAsString(avps[0]); strResult != "300" { // Result-Code set in the template t.Errorf("Expecting 300, received: %s", strResult) } }
func TestClient_Handshake(t *testing.T) { srv := diamtest.NewServer(New(serverSettings), dict.Default) defer srv.Close() cli := &Client{ Handler: New(clientSettings), SupportedVendorID: []*diam.AVP{ diam.NewAVP(avp.SupportedVendorID, avp.Mbit, 0, clientSettings.VendorID), }, AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, AuthApplicationID: []*diam.AVP{ diam.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, VendorSpecificApplicationID: []*diam.AVP{ diam.NewAVP(avp.VendorSpecificApplicationID, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, }), }, } c, err := cli.Dial(srv.Address) if err != nil { t.Fatal(err) } c.Close() }
func NewDiameterClient(addr, originHost, originRealm string, vendorId int, productName string, firmwareRev int) (*DiameterClient, error) { cfg := &sm.Settings{ OriginHost: datatype.DiameterIdentity(originHost), OriginRealm: datatype.DiameterIdentity(originRealm), VendorID: datatype.Unsigned32(vendorId), ProductName: datatype.UTF8String(productName), FirmwareRevision: datatype.Unsigned32(firmwareRev), } handlers := sm.New(cfg) cli := &sm.Client{ Handler: handlers, MaxRetransmits: 3, RetransmitInterval: time.Second, EnableWatchdog: true, WatchdogInterval: 5 * time.Second, AcctApplicationID: []*diam.AVP{ // Advertise that we want support for both // Accounting applications 4 and 999. diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)), // RFC 4006 }, } conn, err := cli.Dial(addr) if err != nil { return nil, err } return &DiameterClient{conn: conn, handlers: handlers}, nil }
func (cli *Client) makeCER(ip net.IP) *diam.Message { m := diam.NewRequest(diam.CapabilitiesExchange, 0, cli.Dict) m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, datatype.Address(ip)) m.NewAVP(avp.VendorID, avp.Mbit, 0, cli.Handler.cfg.VendorID) m.NewAVP(avp.ProductName, 0, 0, cli.Handler.cfg.ProductName) stateid := datatype.Unsigned32(uint32(time.Now().Unix())) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, stateid) if cli.SupportedVendorID != nil { for _, a := range cli.SupportedVendorID { m.AddAVP(a) } } if cli.AuthApplicationID != nil { for _, a := range cli.AuthApplicationID { m.AddAVP(a) } } m.NewAVP(avp.InbandSecurityID, avp.Mbit, 0, datatype.Unsigned32(0)) if cli.AcctApplicationID != nil { for _, a := range cli.AcctApplicationID { m.AddAVP(a) } } if cli.VendorSpecificApplicationID != nil { for _, a := range cli.VendorSpecificApplicationID { m.AddAVP(a) } } m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, cli.Handler.cfg.FirmwareRevision) return m }
// Used when sending from client to agent func (self *CCR) AsDiameterMessage() (*diam.Message, error) { m := self.AsBareDiameterMessage() if _, err := m.NewAVP("Destination-Host", avp.Mbit, 0, datatype.DiameterIdentity(self.DestinationHost)); err != nil { return nil, err } if _, err := m.NewAVP("Destination-Realm", avp.Mbit, 0, datatype.DiameterIdentity(self.DestinationRealm)); err != nil { return nil, err } if _, err := m.NewAVP("Service-Context-Id", avp.Mbit, 0, datatype.UTF8String(self.ServiceContextId)); err != nil { return nil, err } if _, err := m.NewAVP("Event-Timestamp", avp.Mbit, 0, datatype.Time(self.EventTimestamp)); err != nil { return nil, err } for _, subscriptionId := range self.SubscriptionId { if _, err := m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(subscriptionId.SubscriptionIdType)), // Subscription-Id-Type diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String(subscriptionId.SubscriptionIdData)), // Subscription-Id-Data }}); err != nil { return nil, err } } if _, err := m.NewAVP("Service-Identifier", avp.Mbit, 0, datatype.Unsigned32(self.ServiceIdentifier)); err != nil { return nil, err } if _, err := m.NewAVP("Requested-Service-Unit", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(self.RequestedServiceUnit.CCTime))}}); err != nil { // CC-Time return nil, err } if _, err := m.NewAVP("Used-Service-Unit", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(self.UsedServiceUnit.CCTime))}}); err != nil { // CC-Time return nil, err } if _, err := m.NewAVP(873, avp.Mbit, 10415, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(20300, avp.Mbit, 2011, &diam.GroupedAVP{ // IN-Information AVP: []*diam.AVP{ diam.NewAVP(831, avp.Mbit, 10415, datatype.UTF8String(self.ServiceInformation.INInformation.CallingPartyAddress)), // Calling-Party-Address diam.NewAVP(832, avp.Mbit, 10415, datatype.UTF8String(self.ServiceInformation.INInformation.CalledPartyAddress)), // Called-Party-Address diam.NewAVP(20327, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.RealCalledNumber)), // Real-Called-Number diam.NewAVP(20339, avp.Mbit, 2011, datatype.Unsigned32(self.ServiceInformation.INInformation.ChargeFlowType)), // Charge-Flow-Type diam.NewAVP(20302, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.CallingVlrNumber)), // Calling-Vlr-Number diam.NewAVP(20303, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.CallingCellIDOrSAI)), // Calling-CellID-Or-SAI diam.NewAVP(20313, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.BearerCapability)), // Bearer-Capability diam.NewAVP(20321, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.CallReferenceNumber)), // Call-Reference-Number diam.NewAVP(20322, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.MSCAddress)), // MSC-Address diam.NewAVP(20324, avp.Mbit, 2011, datatype.Unsigned32(self.ServiceInformation.INInformation.TimeZone)), // Time-Zone diam.NewAVP(20385, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.CalledPartyNP)), // Called-Party-NP diam.NewAVP(20386, avp.Mbit, 2011, datatype.UTF8String(self.ServiceInformation.INInformation.SSPTime)), // SSP-Time }, }), }}); err != nil { return nil, err } return m, nil }
func TestHandleDWR_Fail(t *testing.T) { sm := New(serverSettings) srv := diamtest.NewServer(sm, dict.Default) defer srv.Close() mc := make(chan *diam.Message, 1) mux := diam.NewServeMux() mux.HandleFunc("CEA", func(c diam.Conn, m *diam.Message) { mc <- m }) mux.HandleFunc("DWA", func(c diam.Conn, m *diam.Message) { mc <- m }) cli, err := diam.Dial(srv.Addr, mux, dict.Default) if err != nil { t.Fatal(err) } defer cli.Close() // Send CER first. m := diam.NewRequest(diam.CapabilitiesExchange, 1001, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, clientSettings.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, clientSettings.OriginRealm) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, localhostAddress) m.NewAVP(avp.VendorID, avp.Mbit, 0, clientSettings.VendorID) m.NewAVP(avp.ProductName, 0, 0, clientSettings.ProductName) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(1001)) m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, clientSettings.FirmwareRevision) _, err = m.WriteTo(cli) if err != nil { t.Fatal(err) } select { case resp := <-mc: if !testResultCode(resp, diam.Success) { t.Fatalf("Unexpected result code for CEA.\n%s", resp) } case err := <-mux.ErrorReports(): t.Fatal(err) case <-time.After(time.Second): t.Fatal("No CEA received") } // Send broken DWR (missing Origin-Host, etc). m = diam.NewRequest(diam.DeviceWatchdog, 0, dict.Default) _, err = m.WriteTo(cli) if err != nil { t.Fatal(err) } select { case err := <-sm.ErrorReports(): if err.Error != smparser.ErrMissingOriginHost { t.Fatalf("Unexpected error. Want ErrMissingOriginHost, have %#v", err.Error) } case err := <-mux.ErrorReports(): t.Fatal(err) case <-time.After(time.Second): t.Fatal("No DWA received") } }
// AsBareDiameterMessage converts CCR into a bare DiameterMessage // Compatible with the required fields of CCA func (self *CCR) AsBareDiameterMessage() *diam.Message { m := diam.NewRequest(diam.CreditControl, 4, nil) m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(self.SessionId)) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity(self.OriginHost)) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity(self.OriginRealm)) m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(self.AuthApplicationId)) m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(self.CCRequestType)) m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(self.CCRequestNumber)) return m }
func sendCER(w io.Writer) (n int64, err error) { m := diam.NewRequest(diam.CapabilitiesExchange, 0, nil) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.OctetString("cli")) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.OctetString("localhost")) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, datatype.Address(net.ParseIP("127.0.0.1"))) m.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(99)) m.NewAVP(avp.ProductName, avp.Mbit, 0, datatype.UTF8String("go-diameter")) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1234)) m.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(1)) return m.WriteTo(w) }
func TestFieldOutVal(t *testing.T) { m := diam.NewRequest(diam.CreditControl, 4, nil) m.NewAVP("Session-Id", avp.Mbit, 0, datatype.UTF8String("simuhuawei;1449573472;00002")) m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(0)), // Subscription-Id-Type diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("33708000003")), // Subscription-Id-Data }}) m.NewAVP("Subscription-Id", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(450, avp.Mbit, 0, datatype.Enumerated(1)), // Subscription-Id-Type diam.NewAVP(444, avp.Mbit, 0, datatype.UTF8String("208708000003")), // Subscription-Id-Data }}) m.NewAVP("Service-Identifier", avp.Mbit, 0, datatype.Unsigned32(0)) m.NewAVP("Requested-Service-Unit", avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(420, avp.Mbit, 0, datatype.Unsigned32(360))}}) // CC-Time cfgFld := &config.CfgCdrField{Tag: "StaticTest", Type: utils.META_COMPOSED, FieldId: utils.TOR, Value: utils.ParseRSRFieldsMustCompile("^*voice", utils.INFIELD_SEP), Mandatory: true} eOut := "*voice" if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0)); err != nil { t.Error(err) } else if fldOut != eOut { t.Errorf("Expecting: %s, received: %s", eOut, fldOut) } cfgFld = &config.CfgCdrField{Tag: "ComposedTest", Type: utils.META_COMPOSED, FieldId: utils.DESTINATION, Value: utils.ParseRSRFieldsMustCompile("Requested-Service-Unit>CC-Time", utils.INFIELD_SEP), Mandatory: true} eOut = "360" if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0)); err != nil { t.Error(err) } else if fldOut != eOut { t.Errorf("Expecting: %s, received: %s", eOut, fldOut) } // Without filter, we shoud get always the first subscriptionId cfgFld = &config.CfgCdrField{Tag: "Grouped1", Type: utils.MetaGrouped, FieldId: "Account", Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true} eOut = "33708000003" if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0)); err != nil { t.Error(err) } else if fldOut != eOut { t.Errorf("Expecting: %s, received: %s", eOut, fldOut) } // Without groupedAVP, we shoud get the first subscriptionId cfgFld = &config.CfgCdrField{Tag: "Grouped2", Type: utils.MetaGrouped, FieldId: "Account", FieldFilter: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Type(1)", utils.INFIELD_SEP), Value: utils.ParseRSRFieldsMustCompile("Subscription-Id>Subscription-Id-Data", utils.INFIELD_SEP), Mandatory: true} eOut = "208708000003" if fldOut, err := fieldOutVal(m, cfgFld, time.Duration(0)); err != nil { t.Error(err) } else if fldOut != eOut { t.Errorf("Expecting: %s, received: %s", eOut, fldOut) } }
// AsBareDiameterMessage converts CCA into a bare DiameterMessage func (self *CCA) AsBareDiameterMessage() *diam.Message { var m diam.Message utils.Clone(self.diamMessage, &m) m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(self.SessionId)) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity(self.OriginHost)) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity(self.OriginRealm)) m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(self.AuthApplicationId)) m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(self.CCRequestType)) m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Enumerated(self.CCRequestNumber)) m.NewAVP(avp.ResultCode, avp.Mbit, 0, datatype.Unsigned32(self.ResultCode)) return &m }
func storedCdrToCCR(cdr *engine.StoredCdr, originHost, originRealm string, vendorId int, productName string, firmwareRev int, debitInterval time.Duration, callEnded bool) *diam.Message { sid := "session;" + strconv.Itoa(int(rand.Uint32())) reqType, reqNr, ccTime := disectUsageForCCR(cdr.Usage, debitInterval, callEnded) m := diam.NewRequest(272, 4, nil) m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(sid)) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity(originHost)) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity(originRealm)) m.NewAVP(avp.DestinationHost, avp.Mbit, 0, datatype.DiameterIdentity(originHost)) m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, datatype.DiameterIdentity(originRealm)) m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)) m.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.UTF8String("*****@*****.**")) m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Enumerated(reqType)) m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Enumerated(reqNr)) m.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Time(cdr.AnswerTime)) m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(0)), diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String(cdr.Account)), }}) m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Enumerated(1)), diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.UTF8String("20921006232651")), }}) m.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(0)) m.NewAVP(avp.RequestedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(ccTime))}}) /* m.NewAVP(avp.ServiceInformation, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(20300, avp.Mbit, 0, &diam.GroupedAVP{ // IN-Information AVP: []*diam.AVP{ diam.NewAVP(avp.CallingPartyAddress, avp.Mbit, 0, datatype.UTF8String(cdr.Account)), diam.NewAVP(avp.CalledPartyAddress, avp.Mbit, 0, datatype.UTF8String(cdr.Destination)), diam.NewAVP(20327, avp.Mbit, 0, datatype.UTF8String(cdr.Destination)), // Real-Called-Number diam.NewAVP(20339, avp.Mbit, 0, datatype.Unsigned32(0)), // Charge-Flow-Type diam.NewAVP(20302, avp.Mbit, 0, datatype.UTF8String("33657954968")), // Calling-Vlr-Number diam.NewAVP(20303, avp.Mbit, 0, datatype.UTF8String("31901485301525")), // Calling-CellID-Or-SAI diam.NewAVP(avp.BearerCapability, avp.Mbit, 0, datatype.UTF8String("31901485301525")), diam.NewAVP(20321, avp.Mbit, 0, datatype.UTF8String("31901485301525")), // Call-Reference-Number diam.NewAVP(avp.MSCAddress, avp.Mbit, 0, datatype.UTF8String("")), diam.NewAVP(20324, avp.Mbit, 0, datatype.UTF8String("0")), // Time-Zone diam.NewAVP(20385, avp.Mbit, 0, datatype.UTF8String("")), // Called-Party-NP diam.NewAVP(20386, avp.Mbit, 0, datatype.UTF8String("20091020120101")), // SSP-Time }, }), }}) */ return m }
func TestCER_NoCommonSecurity(t *testing.T) { m := diam.NewRequest(diam.CapabilitiesExchange, 0, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity("foobar")) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity("test")) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.InbandSecurityID, avp.Mbit, 0, datatype.Unsigned32(1)) cer := new(CER) _, err := cer.Parse(m) if err == nil { t.Fatal("Broken CER was parsed with no errors") } if err != ErrNoCommonSecurity { t.Fatal("Unexpected error:", err) } }
func main() { err := dict.Default.Load(bytes.NewReader(customApp)) if err != nil { log.Fatal(err) } m := diam.NewMessage(1111, diam.RequestFlag, 999, 1, 2, dict.Default) m.NewAVP(avp.ProductName, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(7070, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(10)), diam.NewAVP(8080, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(20)), diam.NewAVP(9090, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(30)), diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(40)), }, }), }, }), }, }) log.Printf("m:\n%s\n", m) var b bytes.Buffer _, err = m.WriteTo(&b) if err != nil { log.Fatal(err) } z, err := diam.ReadMessage(&b, dict.Default) if err != nil { log.Fatal(err) } log.Printf("z:\n%s\n", z) var y customMsg err = z.Unmarshal(&y) if err != nil { log.Fatal(err) } log.Printf("y:\n%+v\n", y) }
func (cli *Client) makeDWR(osid uint32) *diam.Message { m := diam.NewRequest(diam.DeviceWatchdog, 0, cli.Dict) m.NewAVP(avp.OriginHost, avp.Mbit, 0, cli.Handler.cfg.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cli.Handler.cfg.OriginRealm) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(osid)) return m }
func TestClient_Watchdog_Timeout(t *testing.T) { sm := New(serverSettings) var once sync.Once sm.mux.HandleFunc("DWR", func(c diam.Conn, m *diam.Message) { once.Do(func() { m.Answer(diam.UnableToComply).WriteTo(c) }) }) srv := diamtest.NewServer(sm, dict.Default) defer srv.Close() cli := &Client{ MaxRetransmits: 3, RetransmitInterval: 50 * time.Millisecond, EnableWatchdog: true, WatchdogInterval: 50 * time.Millisecond, Handler: New(clientSettings), AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, } c, err := cli.Dial(srv.Address) if err != nil { t.Fatal(err) } defer c.Close() select { case <-c.(diam.CloseNotifier).CloseNotify(): case <-time.After(500 * time.Millisecond): t.Fatal("Timeout waiting for watchdog to disconnect client") } }
func TestClient_Handshake_RetransmitTimeout(t *testing.T) { mux := diam.NewServeMux() var retransmits uint32 mux.HandleFunc("CER", func(c diam.Conn, m *diam.Message) { // Do nothing to force timeout. atomic.AddUint32(&retransmits, 1) }) srv := diamtest.NewServer(mux, dict.Default) defer srv.Close() cli := &Client{ Handler: New(clientSettings), MaxRetransmits: 3, RetransmitInterval: time.Millisecond, AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, } _, err := cli.Dial(srv.Address) if err == nil { t.Fatal("Unexpected CER worked") } if err != ErrHandshakeTimeout { t.Fatal(err) } if n := atomic.LoadUint32(&retransmits); n != 4 { t.Fatalf("Unexpected # of retransmits. Want 4, have %d", n) } }
func TestDWA(t *testing.T) { m := diam.NewMessage(diam.CapabilitiesExchange, 0, 0, 0, 0, nil) m.NewAVP(avp.ResultCode, avp.Mbit, 0, datatype.Unsigned32(diam.Success)) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) dwa := new(DWA) if err := dwa.Parse(m); err != nil { t.Fatal(err) } if dwa.ResultCode != diam.Success { t.Fatalf("Unexpected Result-Code. Want %d, have %d", diam.Success, dwa.ResultCode) } if dwa.OriginStateID != 1 { t.Fatalf("Unexpected Result-Code. Want 1, have %d", dwa.OriginStateID) } }
// handleDWR handles Device-Watchdog-Request messages. // // If mandatory AVPs such as Origin-Host or Origin-Realm are missing, // we ignore the message. // // See RFC 6733 section 5.5 for details. func handleDWR(sm *StateMachine) diam.HandlerFunc { return func(c diam.Conn, m *diam.Message) { dwr := new(smparser.DWR) err := dwr.Parse(m) if err != nil { sm.Error(&diam.ErrorReport{ Conn: c, Message: m, Error: err, }) return } a := m.Answer(diam.Success) a.NewAVP(avp.OriginHost, avp.Mbit, 0, sm.cfg.OriginHost) a.NewAVP(avp.OriginRealm, avp.Mbit, 0, sm.cfg.OriginRealm) stateid := datatype.Unsigned32(time.Now().Unix()) a.NewAVP(avp.OriginStateID, avp.Mbit, 0, stateid) _, err = a.WriteTo(c) if err != nil { sm.Error(&diam.ErrorReport{ Conn: c, Message: m, Error: err, }) } } }
func TestClient_Handshake_FailedResultCode(t *testing.T) { mux := diam.NewServeMux() mux.HandleFunc("CER", func(c diam.Conn, m *diam.Message) { cer := new(smparser.CER) if _, err := cer.Parse(m); err != nil { panic(err) } a := m.Answer(diam.NoCommonApplication) a.NewAVP(avp.OriginHost, avp.Mbit, 0, clientSettings.OriginHost) a.NewAVP(avp.OriginRealm, avp.Mbit, 0, clientSettings.OriginRealm) a.AddAVP(cer.OriginStateID) a.AddAVP(cer.AcctApplicationID[0]) // The one we send below. a.WriteTo(c) }) srv := diamtest.NewServer(mux, dict.Default) defer srv.Close() cli := &Client{ Handler: New(clientSettings), AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, } _, err := cli.Dial(srv.Address) if err == nil { t.Fatal("Unexpected CER worked") } e, ok := err.(*ErrFailedResultCode) if !ok { t.Fatal(err) } if !strings.Contains(e.Error(), "failed Result-Code AVP") { t.Fatal(e.Error()) } }
func sendACR(c diam.Conn, cfg *sm.Settings, n int) { // Get this client's metadata from the connection object, // which is set by the state machine after the handshake. // It contains the peer's Origin-Host and Realm from the // CER/CEA handshake. We use it to populate the AVPs below. meta, ok := smpeer.FromContext(c.Context()) if !ok { log.Fatal("Client connection does not contain metadata") } var err error var m *diam.Message for i := 0; i < n; i++ { m = diam.NewRequest(diam.Accounting, 0, c.Dictionary()) m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(strconv.Itoa(i))) m.NewAVP(avp.OriginHost, avp.Mbit, 0, cfg.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cfg.OriginRealm) m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, meta.OriginRealm) m.NewAVP(avp.AccountingRecordType, avp.Mbit, 0, eventRecord) m.NewAVP(avp.AccountingRecordNumber, avp.Mbit, 0, datatype.Unsigned32(i)) m.NewAVP(avp.DestinationHost, avp.Mbit, 0, meta.OriginHost) if _, err = m.WriteTo(c); err != nil { log.Fatal(err) } } }
func TestClient_Watchdog(t *testing.T) { srv := diamtest.NewServer(New(serverSettings), dict.Default) defer srv.Close() cli := &Client{ EnableWatchdog: true, WatchdogInterval: 100 * time.Millisecond, Handler: New(clientSettings), AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(0)), }, } c, err := cli.Dial(srv.Address) if err != nil { t.Fatal(err) } defer c.Close() resp := make(chan struct{}, 1) dwa := handleDWA(cli.Handler, resp) cli.Handler.mux.HandleFunc("DWA", func(c diam.Conn, m *diam.Message) { dwa(c, m) }) select { case <-resp: case <-time.After(200 * time.Millisecond): t.Fatal("Timeout waiting for DWA") } }
func TestMetaValueExponent(t *testing.T) { m := diam.NewRequest(diam.CreditControl, 4, nil) m.NewAVP("Session-Id", avp.Mbit, 0, datatype.UTF8String("simuhuawei;1449573472;00002")) m.NewAVP(avp.RequestedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.CCMoney, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.UnitValue, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.ValueDigits, avp.Mbit, 0, datatype.Integer64(10000)), diam.NewAVP(avp.Exponent, avp.Mbit, 0, datatype.Integer32(-5)), }, }), diam.NewAVP(avp.CurrencyCode, avp.Mbit, 0, datatype.Unsigned32(33)), }, }), }, }) if val, err := metaValueExponent(m, utils.ParseRSRFieldsMustCompile("Requested-Service-Unit>CC-Money>Unit-Value>Value-Digits;^|;Requested-Service-Unit>CC-Money>Unit-Value>Exponent", utils.INFIELD_SEP), 10); err != nil { t.Error(err) } else if val != "0.1" { t.Error("Received: ", val) } if _, err = metaValueExponent(m, utils.ParseRSRFieldsMustCompile("Requested-Service-Unit>CC-Money>Unit-Value>Value-Digits;Requested-Service-Unit>CC-Money>Unit-Value>Exponent", utils.INFIELD_SEP), 10); err == nil { t.Error("Should have received error") // Insufficient number arguments } }
func TestHandleCER_HandshakeMetadata(t *testing.T) { sm := New(serverSettings) srv := diamtest.NewServer(sm, dict.Default) defer srv.Close() hsc := make(chan diam.Conn, 1) cli, err := diam.Dial(srv.Address, nil, dict.Default) if err != nil { t.Fatal(err) } defer cli.Close() ready := make(chan struct{}) go func() { close(ready) c := <-sm.HandshakeNotify() hsc <- c }() <-ready m := diam.NewRequest(diam.CapabilitiesExchange, 1001, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, clientSettings.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, clientSettings.OriginRealm) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, localhostAddress) m.NewAVP(avp.VendorID, avp.Mbit, 0, clientSettings.VendorID) m.NewAVP(avp.ProductName, 0, 0, clientSettings.ProductName) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(1001)) m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, clientSettings.FirmwareRevision) _, err = m.WriteTo(cli) if err != nil { t.Fatal(err) } select { case c := <-hsc: ctx := c.Context() meta, ok := smpeer.FromContext(ctx) if !ok { t.Fatal("Handshake ok but no context/metadata found") } if meta.OriginHost != clientSettings.OriginHost { t.Fatalf("Unexpected OriginHost. Want %q, have %q", clientSettings.OriginHost, meta.OriginHost) } if meta.OriginRealm != clientSettings.OriginRealm { t.Fatalf("Unexpected OriginRealm. Want %q, have %q", clientSettings.OriginRealm, meta.OriginRealm) } } }
func TestCER_AcctAppID(t *testing.T) { m := diam.NewRequest(diam.CapabilitiesExchange, 0, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity("foobar")) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity("test")) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(1001)) cer := new(CER) _, err := cer.Parse(m) if err != nil { t.Fatal(err) } if app := cer.Applications(); len(app) != 1 { if app[0] != 1001 { t.Fatalf("Unexpected app ID. Want 1001, have %d", app[0]) } } }
func TestMakeGroupedAVP(t *testing.T) { g := &GroupedAVP{ AVP: []*AVP{ NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)), NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(10415)), }, } a := NewAVP(avp.VendorSpecificApplicationID, avp.Mbit, 0, g) b, err := a.Serialize() if err != nil { t.Fatal(err) } if !bytes.Equal(b, testGroupedAVP) { t.Fatalf("Unexpected value.\nWant:\n%s\nHave:\n%s", hex.Dump(testGroupedAVP), hex.Dump(b)) } t.Logf("Message:\n%s", a) }
// Creates the message handlers func (self *DiameterAgent) handlers() diam.Handler { settings := &sm.Settings{ OriginHost: datatype.DiameterIdentity(self.cgrCfg.DiameterAgentCfg().OriginHost), OriginRealm: datatype.DiameterIdentity(self.cgrCfg.DiameterAgentCfg().OriginRealm), VendorID: datatype.Unsigned32(self.cgrCfg.DiameterAgentCfg().VendorId), ProductName: datatype.UTF8String(self.cgrCfg.DiameterAgentCfg().ProductName), FirmwareRevision: datatype.Unsigned32(utils.DIAMETER_FIRMWARE_REVISION), } dSM := sm.New(settings) dSM.HandleFunc("CCR", self.handleCCR) dSM.HandleFunc("ALL", self.handleALL) go func() { for err := range dSM.ErrorReports() { utils.Logger.Err(fmt.Sprintf("<DiameterAgent> StateMachine error: %+v", err)) } }() return dSM }
func sendCEA(w io.Writer, m *diam.Message, OriginStateID, AcctApplicationID *diam.AVP) (n int64, err error) { m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.OctetString("srv")) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.OctetString("localhost")) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, datatype.Address(net.ParseIP("127.0.0.1"))) m.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(99)) m.NewAVP(avp.ProductName, avp.Mbit, 0, datatype.UTF8String("go-diameter")) m.AddAVP(OriginStateID) m.AddAVP(AcctApplicationID) return m.WriteTo(w) }
func TestCER_AuthNotAcctAppID(t *testing.T) { m := diam.NewRequest(diam.CapabilitiesExchange, 0, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, datatype.DiameterIdentity("foobar")) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, datatype.DiameterIdentity("test")) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(1002)) cer := new(CER) _, err := cer.Parse(m) if err == nil { t.Fatal("Broken CER was parsed with no errors") } appErr, ok := err.(*ErrNoCommonApplication) if !ok { t.Fatal(err) } if appErr.ID != 1002 { t.Fatalf("Unexpected app ID. Want 1002, have %d", appErr.ID) } }
func TestHandleCER_VS_Auth_Fail(t *testing.T) { sm := New(serverSettings) srv := diamtest.NewServer(sm, dict.Default) defer srv.Close() mc := make(chan *diam.Message, 1) mux := diam.NewServeMux() mux.HandleFunc("CEA", func(c diam.Conn, m *diam.Message) { mc <- m }) cli, err := diam.Dial(srv.Address, mux, dict.Default) if err != nil { t.Fatal(err) } defer cli.Close() m := diam.NewRequest(diam.CapabilitiesExchange, 0, dict.Default) m.NewAVP(avp.OriginHost, avp.Mbit, 0, clientSettings.OriginHost) m.NewAVP(avp.OriginRealm, avp.Mbit, 0, clientSettings.OriginRealm) m.NewAVP(avp.HostIPAddress, avp.Mbit, 0, localhostAddress) m.NewAVP(avp.VendorID, avp.Mbit, 0, clientSettings.VendorID) m.NewAVP(avp.ProductName, 0, 0, clientSettings.ProductName) m.NewAVP(avp.OriginStateID, avp.Mbit, 0, datatype.Unsigned32(1)) m.NewAVP(avp.VendorSpecificApplicationID, avp.Mbit, 0, &diam.GroupedAVP{ AVP: []*diam.AVP{ diam.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(1000)), }, }) m.NewAVP(avp.FirmwareRevision, avp.Mbit, 0, clientSettings.FirmwareRevision) _, err = m.WriteTo(cli) if err != nil { t.Fatal(err) } select { case resp := <-mc: if !testResultCode(resp, diam.NoCommonApplication) { t.Fatalf("Unexpected result code.\n%s", resp) } case err := <-mux.ErrorReports(): t.Fatal(err) case <-time.After(time.Second): t.Fatal("No message received") } }