Skip to content

Commit 1319a80

Browse files
committed
add Sy STR/SLR
1 parent 0e16686 commit 1319a80

File tree

3 files changed

+91
-28
lines changed

3 files changed

+91
-28
lines changed

internal/ccgrestsrv.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,18 @@ func (s *CCGRestService) Run() {
3030
s.diamClient.run()
3131
}()
3232

33-
//2. arm "/ccr" handler
34-
http.HandleFunc("/ccr", func(w http.ResponseWriter, r *http.Request) {
33+
//2. arm "/ccr/slr/str" handler
34+
http.HandleFunc("/ccr", handler(s, messageGy))
35+
http.HandleFunc("/slr", handler(s, messageSySLR))
36+
http.HandleFunc("/str", handler(s, messageSySTR))
37+
38+
//3. listen and Serve
39+
log.Printf("REST Server Serve at %s\n", configs.LocalRESTServerAddr)
40+
log.Fatal(http.ListenAndServe(configs.LocalRESTServerAddr, nil))
41+
}
42+
43+
func handler(s *CCGRestService, msgType int) func(w http.ResponseWriter, r *http.Request) {
44+
h := func(w http.ResponseWriter, r *http.Request) {
3545
w.Header().Set("content-type", "application/json")
3646
if r.ContentLength == 0 || r.Method != "POST" {
3747
io.WriteString(w, "{\"error\":\"invalid request\"}")
@@ -42,10 +52,7 @@ func (s *CCGRestService) Run() {
4252
io.WriteString(w, "{\"error\":\"invalid request\"}")
4353
return
4454
}
45-
io.WriteString(w, s.diamClient.sendJSON(body))
46-
})
47-
48-
//3. listen and Serve
49-
log.Printf("REST Server Serve at %s\n", configs.LocalRESTServerAddr)
50-
log.Fatal(http.ListenAndServe(configs.LocalRESTServerAddr, nil))
55+
io.WriteString(w, s.diamClient.sendJSON(body, msgType))
56+
}
57+
return h
5158
}

internal/dccclient.go

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
4957
type message struct {
50-
json []byte
58+
msgType int
59+
json []byte
5160
}
5261
type 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

7792
func 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)

test/test-case.http

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
POST htt://127.0.0.1:8080/ccr HTTP/1.1
1+
POST http://127.0.0.1:8080/ccr HTTP/1.1
22
content-type: application/json
33

44
{
@@ -16,4 +16,16 @@ content-type: application/json
1616
"20340:2011": 0
1717
}
1818
}
19+
}
20+
21+
### Sy
22+
POST http://127.0.0.1:8080/slr HTTP/1.1
23+
content-type: application/json
24+
25+
{
26+
"2904:10415": 0,
27+
"Subscription-Id" :{
28+
"Subscription-Id-Type": 0,
29+
"Subscription-Id-Data": "86136"
30+
}
1931
}

0 commit comments

Comments
 (0)