@@ -11,6 +11,7 @@ import (
1111 "math/rand"
1212 "os"
1313 "os/signal"
14+ "strings"
1415 "time"
1516
1617 "github.com/fiorix/go-diameter/v4/diam"
@@ -46,8 +47,16 @@ type diamClient struct {
4647 pcapFile * os.File
4748 pcapWriter * pcapgo.Writer
4849}
50+
51+ const (
52+ messageGy = iota
53+ messageSySLR
54+ messageSySTR
55+ )
56+
4957type message struct {
50- json []byte
58+ msgType int
59+ json []byte
5160}
5261type channels struct {
5362 tx chan message
@@ -69,9 +78,15 @@ func LoadSettings(file string) (Settings, error) {
6978 return configs , nil
7079 }
7180 if configs .ExtraDiameterXML != "" {
72- err = dict .Default .LoadFile (configs .ExtraDiameterXML )
81+ for _ , file := range strings .Split (configs .ExtraDiameterXML , "," ) {
82+ if file != "" {
83+ if err = dict .Default .LoadFile (file ); err != nil {
84+ return configs , err
85+ }
86+ }
87+ }
7388 }
74- return configs , nil
89+ return configs , err
7590}
7691
7792func newDiamClient (setting * Settings ) diamClient {
@@ -93,6 +108,10 @@ func newDiamClient(setting *Settings) diamClient {
93108 //RFC 4006, Credit Control
94109 diam .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (4 )),
95110 },
111+ VendorSpecificApplicationID : []* diam.AVP {
112+ //3GPP-Sy
113+ diam .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (16777302 )),
114+ },
96115 }
97116 return diamClient {
98117 cfg : cfg ,
@@ -121,22 +140,25 @@ func (c *diamClient) run() {
121140 var err error
122141 //var conn diam.Conn
123142
124- //step 1. arm "CCA" handler
125- c . sm . HandleFunc ( "CCA" , func (con diam.Conn , m * diam.Message ) {
143+ //step 1. arm "CCA/SLA/STA " handler
144+ handler := func (con diam.Conn , m * diam.Message ) {
126145 //1. dump in console
127146 if configs .DumpMessage {
128- log .Printf ("Recieve CCA from %s\n %s" , con .RemoteAddr (), m )
147+ log .Printf ("Recieve Message from %s\n %s" , con .RemoteAddr (), m )
129148 }
130149 //2. dump in pcap file
131150 if c .pcapWriter != nil {
132151 if bytes , err := m .Serialize (); err == nil {
133- c .channel .pcap <- message {bytes }
152+ c .channel .pcap <- message {json : bytes }
134153 }
135154 }
136155 //3. return json to sendCCR (that wait on chan rx)
137156 json , _ := JSON2DiamEncoding .Decode (m )
138- c .channel .rx <- message {json }
139- })
157+ c .channel .rx <- message {json : json }
158+ }
159+ c .sm .HandleFunc (diam .CCA , handler )
160+ c .sm .HandleFunc (diam .STA , handler )
161+ c .sm .HandleFunc ("SLA" , handler )
140162
141163 //step 2. connect to diameter server
142164 if c .conn , err = c .client .DialNetwork ("tcp" , c .serverAddress ); err != nil {
@@ -159,40 +181,62 @@ func (c *diamClient) run() {
159181 c .cleanup ()
160182 log .Fatalln ("Client disconnected." )
161183 return
184+ case e := <- c .sm .ErrorReports ():
185+ log .Println ("Client report error: " , e .String ())
162186 case msg , ok := <- c .channel .tx :
163187 if ok {
164- c .sendCCR (msg .json )
188+ c .sendCCR (msg .json , msg . msgType )
165189 }
166190 }
167191 }
168192}
169193
170- func (c * diamClient ) sendJSON (json []byte ) (res string ) {
171- c .channel .tx <- message {json }
194+ func (c * diamClient ) sendJSON (json []byte , msgType int ) (res string ) {
195+ c .channel .tx <- message {json : json , msgType : msgType }
172196 select {
173197 case response , ok := <- c .channel .rx :
174198 if ok {
175199 res = string (response .json )
176200 }
177201 case <- time .After (2 * time .Second ):
178- res = `{"error":"timeout for wating CCA "}`
202+ res = `{"error":"timeout for wating reponse "}`
179203 }
180204 return
181205}
182- func (c * diamClient ) sendCCR (json []byte ) {
206+ func (c * diamClient ) sendCCR (json []byte , msgType int ) {
183207 //CommandCode,272,Credit Control;ApplicationId=4, Diameter Credit Control Application
184- m := diam .NewRequest (272 , 4 , nil )
208+ //CommandCode,8388635;ApplicationId=16777302, Sy
209+ //CommandCode,275;ApplicationId=16777302, Sy STR
210+
211+ var m * diam.Message
185212 meta , _ := smpeer .FromContext (c .conn .Context ())
186213 sid := fmt .Sprintf ("%s;%d;%d" , configs .OriginHost , time .Now ().Unix (), rand .Uint32 ())
214+
215+ if messageGy == msgType {
216+ m = diam .NewRequest (diam .CreditControl , 4 , nil )
217+
218+ m .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (4 ))
219+
220+ } else if messageSySLR == msgType {
221+ m = diam .NewRequest (8388635 , 16777302 , nil )
222+ m .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (16777302 ))
223+
224+ } else if messageSySTR == msgType {
225+ m = diam .NewRequest (diam .SessionTermination , 16777302 , nil )
226+ m .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (16777302 ))
227+
228+ } else {
229+ return
230+ }
231+
187232 m .NewAVP (avp .OriginHost , avp .Mbit , 0 , c .cfg .OriginHost )
188233 m .NewAVP (avp .OriginRealm , avp .Mbit , 0 , c .cfg .OriginRealm )
189234 m .NewAVP (avp .DestinationHost , avp .Mbit , 0 , meta .OriginHost )
190235 m .NewAVP (avp .DestinationRealm , avp .Mbit , 0 , meta .OriginRealm )
191- m .NewAVP (avp .AuthApplicationID , avp .Mbit , 0 , datatype .Unsigned32 (4 ))
192236
193237 if err := JSON2DiamEncoding .Encode (m , json ); err != nil {
194238 res := fmt .Sprintf (`{"error":%s}` , jsonEscape ((err .Error ())))
195- c .channel .rx <- message {[]byte (res )}
239+ c .channel .rx <- message {json : []byte (res )}
196240 return
197241 }
198242
@@ -203,13 +247,13 @@ func (c *diamClient) sendCCR(json []byte) {
203247
204248 //write in console
205249 if configs .DumpMessage {
206- log .Printf ("Sending CCR to %s\n %s" , c .conn .RemoteAddr (), m )
250+ log .Printf ("Sending message to %s\n %s" , c .conn .RemoteAddr (), m )
207251 }
208252
209253 //write pcap file if configured
210254 if c .pcapWriter != nil {
211255 if bytes , err := m .Serialize (); err == nil {
212- c .channel .pcap <- message {bytes }
256+ c .channel .pcap <- message {json : bytes }
213257 }
214258 }
215259 m .WriteTo (c .conn )
0 commit comments