Documentation ¶
Overview ¶
Package go-diameter provides support for the Diameter protocol for Go. See RFC 6733.
go-diameter is minimalist implementation of the Diameter base protocol, organized in sub-packages with specific functionality:
diam: the main package, provides the capability of encoding and decoding messages, and a client and server API similar to net/http.
diam/avp: implementation of Diameter attribute-value-pairs.
diam/avp/format: AVP data formats (e.g. Unsigned32, OctetString).
diam/dict: a dictionary parser that supports collections of dictionaries.
diam/util: utilities for our sub-packages.
If you're looking to go right into code, see the examples subdirectory for applications like clients and servers.
Diameter Applications ¶
All diameter applications require at least the following:
- A dictionary with the application id, its commands and message formats
- A program that implements the application, driven by the dictionary
The diam/dict sub-package supports the base application (id 0, RFC 6733) and the credit control application (id 4, RFC 4006). Each application has its own commands and messages, and their pre-defined AVPs.
AVP data have specific formats, like UTF8String, Unsigned32 and so on. Fortunately, those types map align well with Go types, which makes things easier for us. However, the AVP data formats have specific properties like padding for certain strings, which have to be taken care of. The sub-package diam/avp/format handles it all.
At last, the diam package is used to build clients and servers using an API very similar to the one of net/http. To initiate the client or server, you'll have to pass a dictionary. Messages sent and received are encoded and decoded using the dictionary automatically.
The API of clients and servers require that you assign handlers for certain messages, similar to how you route HTTP endpoints. In the handlers, you'll receive messages already decoded.
Index ¶
- Constants
- Variables
- func ErrorReports() chan ErrorReport
- func Handle(cmd string, handler Handler)
- func HandleFunc(cmd string, handler func(Conn, *Message))
- func ListenAndServe(addr string, handler Handler, dp *dict.Parser) error
- func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler, dp *dict.Parser) error
- func Serve(l net.Listener, handler Handler) error
- type AVP
- type CloseNotifier
- type Conn
- type ErrorReport
- type GroupedAVP
- type Handler
- type HandlerFunc
- type Header
- type Message
- func (m *Message) AddAVP(a *AVP)
- func (m *Message) Answer(resultCode uint32) *Message
- func (m *Message) FindAVP(code interface{}) (*AVP, error)
- func (m *Message) Len() int
- func (m *Message) NewAVP(code interface{}, flags uint8, vendor uint32, data format.Format) (*AVP, error)
- func (m *Message) Serialize() []byte
- func (m *Message) SerializeTo(b []byte)
- func (m *Message) String() string
- func (m *Message) Unmarshal(dst interface{}) error
- func (m *Message) WriteTo(writer io.Writer) (int64, error)
- type ServeMux
- type Server
Constants ¶
const ( MultiRoundAuth = 1001 Success = 2001 LimitedSuccess = 2002 CommandUnsupported = 3001 UnableToDeliver = 3002 RealmNotServed = 3003 TooBusy = 3004 LoopDetected = 3005 RedirectIndication = 3006 ApplicationUnsupported = 3007 InvalidHDRBits = 3008 InvalidAVPBits = 3009 UnknownPeer = 3010 AuthenticationRejected = 4001 OutOfSpace = 4002 ElectionLost = 4003 AVPUnsupported = 5001 UnknownSessionId = 5002 AuthorizationRejected = 5003 InvalidAVPValue = 5004 MissingAVP = 5005 ResourcesExceeded = 5006 ContradictingAVPs = 5007 AVPNotAllowed = 5008 AVPOccursTooManyTimes = 5009 NoCommonApplication = 5010 UnsupportedVersion = 5011 UnableToComply = 5012 InvalidBitInHeader = 5013 InvalidAVPLenght = 5014 InvalidMessageLength = 5015 InvalidAVPBitCombo = 5016 NoCommonSecurity = 5017 )
Diameter result codes.
const ( AbortSession = 274 Accounting = 271 CapabilitiesExchange = 257 CreditControl = 272 DeviceWatchdog = 280 DisconnectPeer = 282 ReAuth = 258 SessionTermination = 275 )
const ( RequestFlag = 1 << 7 ProxiableFlag = 1 << 6 ErrorFlag = 1 << 5 RetransmittedFlag = 1 << 4 )
Command flags.
const GroupedAVPFormat = 50 // Must not conflict with other format.DataFormatId.
const HeaderLength = 20 // Diameter header length.
Variables ¶
var DefaultServeMux = NewServeMux()
DefaultServeMux is the default ServeMux used by Serve.
Functions ¶
func ErrorReports ¶
func ErrorReports() chan ErrorReport
ErrorReport returns the ErrorReport channel of the DefaultServeMux.
func HandleFunc ¶
HandleFunc registers the handler function for the given command in the DefaultServeMux.
func ListenAndServe ¶
ListenAndServe listens on the TCP network address addr and then calls Serve with handler to handle requests on incoming connections.
If handler is nil, diam.DefaultServeMux is used.
If dict is nil, dict.Default is used.
func ListenAndServeTLS ¶
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler Handler, dp *dict.Parser) error
ListenAndServeTLS acts identically to ListenAndServe, except that it expects SSL connections. Additionally, files containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.
One can use generate_cert.go in crypto/tls to generate cert.pem and key.pem.
Types ¶
type AVP ¶
type AVP struct { Code uint32 // Code of this AVP Flags uint8 // Flags of this AVP Length int // Length of this AVP's payload VendorId uint32 // VendorId of this AVP Data format.Format // Data of this AVP (payload) }
Diameter AVP.
func DecodeAVP ¶
Decode decodes the bytes of a Diameter AVP. It uses the given application id and dictionary for decoding the bytes.
func (*AVP) DecodeFromBytes ¶
DecodeFromBytes decodes the bytes of a Diameter AVP. It uses the given application id and dictionary for decoding the bytes.
func (*AVP) Serialize ¶
Serialize returns the byte sequence that represents this AVP. It requires at least the Code, Flags and Data fields set.
func (*AVP) SerializeTo ¶
type CloseNotifier ¶
type CloseNotifier interface { // CloseNotify returns a channel that is closed // when the client connection has gone away. CloseNotify() <-chan struct{} }
The CloseNotifier interface is implemented by Conns which allow detecting when the underlying connection has gone away.
This mechanism can be used to detect if the client has disconnected.
type Conn ¶
type Conn interface { Write(b []byte) (int, error) // Writes a msg to the connection Close() // Close the connection LocalAddr() net.Addr // Local IP RemoteAddr() net.Addr // Remote IP TLS() *tls.ConnectionState // or nil when not using TLS }
Conn interface is used by a handler to send diameter messages.
type ErrorReport ¶
ErrorReport is sent out of the server in case it fails to read messages because of a bad dictionary, or due to network errors.
type GroupedAVP ¶
type GroupedAVP struct {
AVP []*AVP
}
GroupedAVP that is different from the dummy format.Grouped.
func DecodeGrouped ¶
func (*GroupedAVP) Format ¶
func (g *GroupedAVP) Format() format.FormatId
func (*GroupedAVP) Len ¶
func (g *GroupedAVP) Len() int
func (*GroupedAVP) Padding ¶
func (g *GroupedAVP) Padding() int
func (*GroupedAVP) Serialize ¶
func (g *GroupedAVP) Serialize() []byte
func (*GroupedAVP) String ¶
func (g *GroupedAVP) String() string
type Handler ¶
type Handler interface { ServeDIAM(Conn, *Message) ErrorReports() chan ErrorReport }
Objects implementing the Handler interface can be registered to serve particular messages like CER, DWR.
ServeDIAM should write messages to the Conn and then return. Returning signals that the request is finished and that the server can move on to the next request on the connection.
type HandlerFunc ¶
The HandlerFunc type is an adapter to allow the use of ordinary functions as diameter handlers. If f is a function with the appropriate signature, HandlerFunc(f) is a Handler object that calls f.
func (HandlerFunc) ErrorReports ¶
func (f HandlerFunc) ErrorReports() chan ErrorReport
ErrorReports calls f.ErrorReports()
func (HandlerFunc) ServeDIAM ¶
func (f HandlerFunc) ServeDIAM(c Conn, m *Message)
ServeDIAM calls f(c, m).
type Header ¶
type Header struct { Version uint8 MessageLength uint32 CommandFlags uint8 CommandCode uint32 ApplicationId uint32 HopByHopId uint32 EndToEndId uint32 }
Diameter Header.
func DecodeHeader ¶
DecodeHeader decodes the bytes of a Diameter Header.
func (*Header) DecodeFromBytes ¶
DecodeFromBytes decodes the bytes of a Diameter Header.
func (*Header) SerializeTo ¶
SerializeTo serializes the header to a byte sequence in network byte order.
type Message ¶
type Message struct { Header *Header AVP []*AVP Dictionary *dict.Parser // Used to encode and decode AVPs. }
Diameter message.
func NewMessage ¶
func NewMessage(cmd uint32, flags uint8, appid, hopbyhop, endtoend uint32, dictionary *dict.Parser) *Message
NewMessage creates and initializes Message.
func NewRequest ¶
NewRequest is an alias to NewMessage.
func ReadMessage ¶
ReadMessage returns a Message. It uses the dictionary to parse the binary stream from the reader.
func (*Message) Answer ¶
Answer creates an answer for the current Message with an embedded Result-Code AVP.
func (*Message) FindAVP ¶
FindAVP searches the Message for a specific AVP. The code can be either the AVP code (int, uint32) or name (string).
Example:
avp, err := m.FindAVP(264) avp, err := m.FindAVP("Origin-Host")
func (*Message) NewAVP ¶
func (m *Message) NewAVP(code interface{}, flags uint8, vendor uint32, data format.Format) (*AVP, error)
NewAVP creates and initializes a new AVP and adds it to the Message.
func (*Message) SerializeTo ¶
func (*Message) Unmarshal ¶
Unmarshal stores the result of a diameter message in the struct pointed to by dst.
Unmarshal can not only decode AVPs into the struct, but also their Go equivalent data types, directly.
For example:
type CER struct { OriginHost AVP `avp:"Origin-Host"` .. or OriginHost *AVP `avp:"Origin-Host"` .. or OriginHost string `avp:"Origin-Host"` } var d CER err := diam.Unmarshal(&d)
This decodes the Origin-Host AVP as three different types. The first, AVP, makes a copy of the AVP in the message and stores in the struct. The second, *AVP, stores a pointer to the original AVP in the message. If you change the values of it, you're actually changing the message. The third decodes the inner contents of AVP.Data, which in this case is a format.DiameterIdentity, and stores the value of it in the struct.
Unmarshal supports all the basic Go types, including slices, for multiple AVPs of the same type) and structs, for grouped AVPs.
Slices:
type CER struct { Vendors []*AVP `avp:"Supported-Vendor-Id"` } var d CER err := diam.Unmarshal(&d)
Slices have the same principles of other types. If they're of type []*AVP it'll store references in the struct, while []AVP makes copies and []int (or []string, etc) decodes the AVP data for you.
Grouped AVPs:
type VSA struct { AuthAppId int `avp:"Auth-Application-Id"` VendorId int `avp:"Vendor-Id"` } type CER struct { VSA VSA `avp:"Vendor-Specific-Application-Id"` .. or VSA *VSA `avp:"Vendor-Specific-Application-Id"` .. or VSA struct { AuthAppId int `avp:"Auth-Application-Id"` VendorId int `avp:"Vendor-Id"` } `avp:"Vendor-Specific-Application-Id"` } var d CER err := m.Unmarshal(&d)
Other types are supported as well, such as net.IP and time.Time where applicable. See the format sub-package for details. Usually, you want to decode values to their native Go type when the AVPs don't have to be re-used in an answer, such as Origin-Host and friends. The ones that are usually added to responses, such as Origin-State-Id are better decoded to just AVP or *AVP, making it easier to re-use them in the answer.
Note that decoding values to *AVP is much faster and more efficient than decoding to AVP or the native Go types.
type ServeMux ¶
type ServeMux struct {
// contains filtered or unexported fields
}
ServeMux is a diameter message multiplexer. It matches the command from the incoming message against a list of registered commands and calls the handler.
func (*ServeMux) ErrorReports ¶
func (mux *ServeMux) ErrorReports() chan ErrorReport
ErrorReports returns the ErrorReport channel of the handler.
func (*ServeMux) Handle ¶
Handle registers the handler for the given code. If a handler already exists for code, Handle panics.
func (*ServeMux) HandleFunc ¶
HandleFunc registers the handler function for the given command. Special cmd "ALL" may be used as a catch all.
type Server ¶
type Server struct { Addr string // TCP address to listen on, ":3868" if empty Handler Handler // handler to invoke, diam.DefaultServeMux if nil Dict *dict.Parser // diameter dictionaries for this server ReadTimeout time.Duration // maximum duration before timing out read of the request WriteTimeout time.Duration // maximum duration before timing out write of the response TLSConfig *tls.Config // optional TLS config, used by ListenAndServeTLS }
A Server defines parameters for running a diameter server.
func (*Server) ListenAndServe ¶
ListenAndServe listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming connections. If srv.Addr is blank, ":3868" is used.
func (*Server) ListenAndServeTLS ¶
ListenAndServeTLS listens on the TCP network address srv.Addr and then calls Serve to handle requests on incoming TLS connections.
Filenames containing a certificate and matching private key for the server must be provided. If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate followed by the CA's certificate.
If srv.Addr is blank, ":3868" is used.