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 }
// 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 main() { addr := flag.String("addr", ":3868", "address in the form of ip:port to listen on") ppaddr := flag.String("pprof_addr", ":9000", "address in form of ip:port for the pprof server") host := flag.String("diam_host", "server", "diameter identity host") realm := flag.String("diam_realm", "go-diameter", "diameter identity realm") certFile := flag.String("cert_file", "", "tls certificate file (optional)") keyFile := flag.String("key_file", "", "tls key file (optional)") silent := flag.Bool("s", false, "silent mode, useful for benchmarks") flag.Parse() // Load our custom dictionary on top of the default one, which // always have the Base Protocol (RFC6733) and Credit Control // Application (RFC4006). err := dict.Default.Load(bytes.NewReader([]byte(helloDictionary))) if err != nil { log.Fatal(err) } settings := &sm.Settings{ OriginHost: datatype.DiameterIdentity(*host), OriginRealm: datatype.DiameterIdentity(*realm), VendorID: 13, ProductName: "go-diameter", FirmwareRevision: 1, } // Create the state machine (mux) and set its message handlers. mux := sm.New(settings) mux.Handle("HMR", handleHMR(*silent)) mux.Handle("ACR", handleACR(*silent)) mux.HandleFunc("ALL", handleALL) // Catch all. // Print error reports. go printErrors(mux.ErrorReports()) if len(*ppaddr) > 0 { go func() { log.Fatal(http.ListenAndServe(*ppaddr, nil)) }() } err = listen(*addr, *certFile, *keyFile, mux) if err != nil { log.Fatal(err) } }
func NewDiameterClient(addr, originHost, originRealm string, vendorId int, productName string, firmwareRev int, dictsDir string) (*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), } dSM := sm.New(cfg) go func() { for err := range dSM.ErrorReports() { utils.Logger.Err(fmt.Sprintf("<DiameterClient> StateMachine error: %+v", err)) } }() cli := &sm.Client{ Handler: dSM, MaxRetransmits: 3, RetransmitInterval: time.Second, EnableWatchdog: true, WatchdogInterval: 5 * time.Second, AcctApplicationID: []*diam.AVP{ diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(4)), // RFC 4006 }, } if len(dictsDir) != 0 { if err := loadDictionaries(dictsDir, "DiameterClient"); err != nil { return nil, err } } conn, err := cli.Dial(addr) if err != nil { return nil, err } dc := &DiameterClient{conn: conn, handlers: dSM} dSM.HandleFunc("ALL", dc.handleALL) return dc, nil }
func main() { addr := flag.String("addr", "localhost:3868", "address in form of ip:port to connect to") ssl := flag.Bool("ssl", false, "connect to server using tls") host := flag.String("diam_host", "client", "diameter identity host") realm := flag.String("diam_realm", "go-diameter", "diameter identity realm") certFile := flag.String("cert_file", "", "tls client certificate file (optional)") keyFile := flag.String("key_file", "", "tls client key file (optional)") hello := flag.Bool("hello", false, "send a hello message, wait for the response and disconnect") bench := flag.Bool("bench", false, "benchmark the server by sending ACR messages") benchCli := flag.Int("bench_clients", 1, "number of client connections") benchMsgs := flag.Int("bench_msgs", 1000, "number of ACR messages to send") flag.Parse() if len(*addr) == 0 { flag.Usage() } // Load our custom dictionary on top of the default one. err := dict.Default.Load(bytes.NewReader([]byte(helloDictionary))) if err != nil { log.Fatal(err) } cfg := &sm.Settings{ OriginHost: datatype.DiameterIdentity(*host), OriginRealm: datatype.DiameterIdentity(*realm), VendorID: 13, ProductName: "go-diameter", OriginStateID: datatype.Unsigned32(time.Now().Unix()), FirmwareRevision: 1, } // Create the state machine (it's a diam.ServeMux) and client. mux := sm.New(cfg) cli := &sm.Client{ Dict: dict.Default, Handler: mux, 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 diam.NewAVP(avp.AcctApplicationID, avp.Mbit, 0, datatype.Unsigned32(helloApplication)), }, } // Set message handlers. done := make(chan struct{}, 1000) mux.Handle("HMA", handleHMA(done)) mux.Handle("ACA", handleACA(done)) // Print error reports. go printErrors(mux.ErrorReports()) connect := func() (diam.Conn, error) { return dial(cli, *addr, *certFile, *keyFile, *ssl) } if *bench { cli.EnableWatchdog = false benchmark(connect, cfg, *benchCli, *benchMsgs, done) return } if *hello { c, err := connect() if err != nil { log.Fatal(err) } err = sendHMR(c, cfg) if err != nil { log.Fatal(err) } select { case <-done: case <-time.After(5 * time.Second): log.Fatal("timeout: no hello answer received") } return } // Makes a persisent connection with back-off. log.Println("Use wireshark to see the messages, or try -hello") backoff := 1 for { c, err := connect() if err != nil { log.Println(err) backoff *= 2 if backoff > 20 { backoff = 20 } time.Sleep(time.Duration(backoff) * time.Second) continue } log.Println("Client connected, handshake ok") backoff = 1 <-c.(diam.CloseNotifier).CloseNotify() log.Println("Client disconnected") } }