297ocsadapter
261 строка · 8.9 Кб
1package client2
3import (4"github.com/fiorix/go-diameter/v4/diam"5"github.com/fiorix/go-diameter/v4/diam/avp"6"github.com/fiorix/go-diameter/v4/diam/datatype"7"github.com/fiorix/go-diameter/v4/diam/dict"8"github.com/fiorix/go-diameter/v4/diam/sm"9"github.com/fiorix/go-diameter/v4/diam/sm/smpeer"10"istio.io/pkg/log"11"net"12"strconv"13"time"14)
15
16var mux *sm.StateMachine17var done = make(chan *diam.Message, 1000)18var cfg *sm.Settings19var conn diam.Conn20
21func GetUnits(ocsAddress string, applicationId string, requestUnits []string, used int) int {22createMux(ocsAddress)23forceUpdate := false24for i := range requestUnits {25units, err := strconv.Atoi(requestUnits[i])26if err != nil {27log.Fatalf("Couldn't parse a value %v", requestUnits[0])28}29if used != 0 || forceUpdate {30sendCCRU(applicationId, used, units)31} else {32sendCCRI(applicationId, units)33}34select {35case m := <-done:36resultCodeAvp, err := m.FindAVP(avp.ResultCode, 0)37if err != nil {38log.Warnf("Couldn't find Result-Code AVP in response for %s", applicationId)39return 040}41resultCode := int(resultCodeAvp.Data.(datatype.Unsigned32))42if resultCode == 4012 {43used = 044forceUpdate = true45continue46}47timeAvp, err := m.FindAVP(avp.CCTime, 0)48if err != nil {49log.Warnf("Couldn't find CC-Time AVP in response for %s", applicationId)50return 051}52grantedAmount := int(timeAvp.Data.(datatype.Unsigned32))53log.Infof("grantedAmount: %v", grantedAmount)54return grantedAmount55case <-time.After(5 * time.Second):56log.Fatalf("timeout: no hello answer received")57}58}59return 060}
61
62func Terminate(usedMap map[string]int) {63if conn == nil {64return65}66for applicationId, used := range usedMap {67sendCCRT(applicationId, used)68}69}
70
71func createMux(ocsAddress string) {72if mux != nil && conn.RemoteAddr().String() == ocsAddress {73return74}75host := "client"76realm := "ocs-adapter"77networkType := "tcp"78
79cfg = &sm.Settings{80OriginHost: datatype.DiameterIdentity(host),81OriginRealm: datatype.DiameterIdentity(realm),82VendorID: 13,83ProductName: "go-diameter",84OriginStateID: datatype.Unsigned32(time.Now().Unix()),85FirmwareRevision: 1,86HostIPAddresses: []datatype.Address{87datatype.Address(net.ParseIP("127.0.0.1")),88},89}90
91// Create the state machine (it's a diam.ServeMux) and client.92mux = sm.New(cfg)93
94cli := &sm.Client{95Dict: dict.Default,96Handler: mux,97MaxRetransmits: 0,98RetransmitInterval: time.Second,99EnableWatchdog: false,100WatchdogInterval: 5 * time.Second,101SupportedVendorID: []*diam.AVP{102diam.NewAVP(avp.SupportedVendorID, avp.Mbit, 0, datatype.Unsigned32(10415)),103},104VendorSpecificApplicationID: []*diam.AVP{105diam.NewAVP(avp.VendorSpecificApplicationID, avp.Mbit, 0, &diam.GroupedAVP{106AVP: []*diam.AVP{107diam.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)),108diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(10415)),109},110}),111},112}113
114// Set message handlers.115mux.Handle(diam.CCA, handleCCA())116
117// Print error reports.118go printErrors(mux.ErrorReports())119
120// Makes a persistent connection with back-off.121c, err := cli.DialNetwork(networkType, ocsAddress)122if err != nil {123log.Fatalf(err.Error())124}125conn = c126}
127
128func printErrors(ec <-chan *diam.ErrorReport) {129for err := range ec {130log.Fatalf(err.String())131}132}
133
134func sendCCRI(applicationId string, requestUnits int) {135log.Infof("send CCR to %v", conn.RemoteAddr().String())136meta, ok := smpeer.FromContext(conn.Context())137if !ok {138log.Fatalf("Client connection does not contain metadata")139}140subscriptionId, _ := strconv.ParseUint(applicationId, 10, 32)141m := diam.NewRequest(diam.CreditControl, 4, dict.Default)142m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4))143m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(strconv.Itoa(0)))144m.NewAVP(avp.OriginHost, avp.Mbit, 0, cfg.OriginHost)145m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cfg.OriginRealm)146m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, meta.OriginRealm)147m.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.OctetString("32251@3gpp.org"))148m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{149AVP: []*diam.AVP{150diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Unsigned32(3)),151diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.OctetString(applicationId)),152},153})154m.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Unsigned32(time.Now().Unix()))155m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Unsigned32(1))156m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(0))157m.NewAVP(avp.MultipleServicesCreditControl, avp.Mbit, 0, &diam.GroupedAVP{158AVP: []*diam.AVP{159diam.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(uint32(subscriptionId))),160diam.NewAVP(avp.RatingGroup, avp.Mbit, 0, datatype.Unsigned32(0)),161diam.NewAVP(avp.RequestedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{162AVP: []*diam.AVP{163diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(requestUnits)),164},165}),166},167})168if _, err := m.WriteTo(conn); err != nil {169log.Fatalf(err.Error())170}171}
172
173func sendCCRU(applicationId string, used int, requestUnits int) {174log.Infof("send CCR to %v", conn.RemoteAddr().String())175meta, ok := smpeer.FromContext(conn.Context())176if !ok {177log.Fatalf("Client connection does not contain metadata")178}179subscriptionId, _ := strconv.ParseUint(applicationId, 10, 32)180m := diam.NewRequest(diam.CreditControl, 4, dict.Default)181m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4))182m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(strconv.Itoa(0)))183m.NewAVP(avp.OriginHost, avp.Mbit, 0, cfg.OriginHost)184m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cfg.OriginRealm)185m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, meta.OriginRealm)186m.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.OctetString("32251@3gpp.org"))187m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{188AVP: []*diam.AVP{189diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Unsigned32(3)),190diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.OctetString(applicationId)),191},192})193m.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Unsigned32(time.Now().Unix()))194m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Unsigned32(2))195m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(0))196m.NewAVP(avp.MultipleServicesCreditControl, avp.Mbit, 0, &diam.GroupedAVP{197AVP: []*diam.AVP{198diam.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(uint32(subscriptionId))),199diam.NewAVP(avp.RatingGroup, avp.Mbit, 0, datatype.Unsigned32(0)),200diam.NewAVP(avp.UsedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{201AVP: []*diam.AVP{202diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(used)),203},204}),205diam.NewAVP(avp.RequestedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{206AVP: []*diam.AVP{207diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(requestUnits)),208},209}),210},211})212if _, err := m.WriteTo(conn); err != nil {213log.Fatalf(err.Error())214}215}
216
217func sendCCRT(applicationId string, used int) {218log.Infof("send CCR to %v", conn.RemoteAddr().String())219meta, ok := smpeer.FromContext(conn.Context())220if !ok {221log.Fatalf("Client connection does not contain metadata")222}223subscriptionId, _ := strconv.ParseUint(applicationId, 10, 32)224m := diam.NewRequest(diam.CreditControl, 4, dict.Default)225m.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(4))226m.NewAVP(avp.SessionID, avp.Mbit, 0, datatype.UTF8String(strconv.Itoa(0)))227m.NewAVP(avp.OriginHost, avp.Mbit, 0, cfg.OriginHost)228m.NewAVP(avp.OriginRealm, avp.Mbit, 0, cfg.OriginRealm)229m.NewAVP(avp.DestinationRealm, avp.Mbit, 0, meta.OriginRealm)230m.NewAVP(avp.ServiceContextID, avp.Mbit, 0, datatype.OctetString("32251@3gpp.org"))231m.NewAVP(avp.SubscriptionID, avp.Mbit, 0, &diam.GroupedAVP{232AVP: []*diam.AVP{233diam.NewAVP(avp.SubscriptionIDType, avp.Mbit, 0, datatype.Unsigned32(3)),234diam.NewAVP(avp.SubscriptionIDData, avp.Mbit, 0, datatype.OctetString(applicationId)),235},236})237m.NewAVP(avp.EventTimestamp, avp.Mbit, 0, datatype.Unsigned32(time.Now().Unix()))238m.NewAVP(avp.CCRequestType, avp.Mbit, 0, datatype.Unsigned32(3))239m.NewAVP(avp.CCRequestNumber, avp.Mbit, 0, datatype.Unsigned32(0))240m.NewAVP(avp.MultipleServicesCreditControl, avp.Mbit, 0, &diam.GroupedAVP{241AVP: []*diam.AVP{242diam.NewAVP(avp.ServiceIdentifier, avp.Mbit, 0, datatype.Unsigned32(uint32(subscriptionId))),243diam.NewAVP(avp.RatingGroup, avp.Mbit, 0, datatype.Unsigned32(0)),244diam.NewAVP(avp.UsedServiceUnit, avp.Mbit, 0, &diam.GroupedAVP{245AVP: []*diam.AVP{246diam.NewAVP(avp.CCTime, avp.Mbit, 0, datatype.Unsigned32(used)),247},248}),249},250})251if _, err := m.WriteTo(conn); err != nil {252log.Fatalf(err.Error())253}254}
255
256func handleCCA() diam.HandlerFunc {257return func(c diam.Conn, m *diam.Message) {258log.Infof("Received CCA from %s\n%s", c.RemoteAddr(), m)259done <- m260}261}
262