/
s6a_proxy.go
124 lines (110 loc) · 3.82 KB
/
s6a_proxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// package servce implements S6a GRPC proxy service which sends AIR, ULR messages over diameter connection,
// waits (blocks) for diameter's AIAs, ULAs & returns their RPC representation
package service
import (
"net"
"sync"
"time"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/diam"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/diam/avp"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/diam/datatype"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/diam/dict"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/diam/sm"
"github.com/ParspooyeshFanavar/go-diameter-v3/v3/examples/s6a_proxy/protos"
"golang.org/x/net/context"
)
const (
ULR_RAT_TYPE = 1004
ULR_FLAGS = 1<<1 | 1<<5
TIMEOUT_SECONDS = 10
MAX_DIAM_RETRIES = 1
PRODUCT_NAME = "s6a_proxy"
)
type s6aProxy struct {
mu sync.RWMutex
cfg *S6aProxyConfig
smClient *sm.Client
conn diam.Conn
sessionsMu sync.Mutex
sessions map[string]chan interface{}
}
func NewS6aProxy(cfg *S6aProxyConfig) (*s6aProxy, error) {
err := cfg.Validate()
if err != nil {
return nil, err
}
cfg = cfg.CloneWithDefaults()
mux := sm.New(&sm.Settings{
OriginHost: datatype.DiameterIdentity(cfg.Host),
OriginRealm: datatype.DiameterIdentity(cfg.Realm),
VendorID: datatype.Unsigned32(VENDOR_3GPP),
ProductName: PRODUCT_NAME,
OriginStateID: datatype.Unsigned32(time.Now().Unix()),
FirmwareRevision: 1,
HostIPAddresses: []datatype.Address{
datatype.Address(net.ParseIP("127.0.0.1")),
},
})
mux.HandleFunc("ALL", func(diam.Conn, *diam.Message) {}) // Catch all.
proxy := &s6aProxy{
cfg: cfg,
smClient: &sm.Client{
Dict: dict.Default,
Handler: mux,
MaxRetransmits: cfg.Retransmits,
RetransmitInterval: time.Second,
EnableWatchdog: true,
WatchdogInterval: time.Second * time.Duration(cfg.WatchdogInterval),
SupportedVendorID: []*diam.AVP{
diam.NewAVP(avp.SupportedVendorID, avp.Mbit, 0, datatype.Unsigned32(VENDOR_3GPP)),
},
VendorSpecificApplicationID: []*diam.AVP{
diam.NewAVP(avp.VendorSpecificApplicationID, avp.Mbit, 0, &diam.GroupedAVP{
AVP: []*diam.AVP{
diam.NewAVP(avp.AuthApplicationID, avp.Mbit, 0, datatype.Unsigned32(diam.TGPP_S6A_APP_ID)),
diam.NewAVP(avp.VendorID, avp.Mbit, 0, datatype.Unsigned32(diam.TGPP_S6A_APP_ID)),
},
}),
},
},
conn: nil,
sessions: make(map[string]chan interface{}),
}
mux.HandleIdx(
diam.CommandIndex{AppID: diam.TGPP_S6A_APP_ID, Code: diam.AuthenticationInformation, Request: false},
handleAIA(proxy))
mux.HandleIdx(
diam.CommandIndex{AppID: diam.TGPP_S6A_APP_ID, Code: diam.UpdateLocation, Request: false},
handleULA(proxy))
return proxy, nil
}
// S6AProxyServer implementation
//
// AuthenticationInformation sends AIR over diameter connection,
// waits (blocks) for AIA & returns its RPC representation
func (s *s6aProxy) AuthenticationInformation(
ctx context.Context, req *protos.AuthenticationInformationRequest) (*protos.AuthenticationInformationAnswer, error,
) {
return s.AuthenticationInformationImpl(req)
}
// UpdateLocation sends ULR (Code 316) over diameter connection,
// waits (blocks) for ULAA & returns its RPC representation
func (s *s6aProxy) UpdateLocation(
ctx context.Context, req *protos.UpdateLocationRequest) (*protos.UpdateLocationAnswer, error,
) {
return s.UpdateLocationImpl(req)
}
// CancelLocation sends CLR (Code 317) over diameter connection,
// Not implemented for now
func (s *s6aProxy) CancelLocation(
ctx context.Context, req *protos.CancelLocationRequest) (*protos.CancelLocationAnswer, error,
) {
panic("Not implemented")
}
// PurgeUE sends PUR (Code 321) over diameter connection,
// Not implemented
func (s *s6aProxy) PurgeUE(
ctx context.Context, req *protos.PurgeUERequest) (*protos.PurgeUEAnswer, error,
) {
panic("Not implemented")
}