Skip to content

Commit af3f806

Browse files
committed
ref: gathers all sctp config in one struct
1 parent 0444935 commit af3f806

5 files changed

Lines changed: 69 additions & 49 deletions

File tree

client.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@ import (
1818
// signals and heartbeats are automatically handled background in another goroutine.
1919
func Dial(ctx context.Context, net string, laddr, raddr *sctp.SCTPAddr, cfg *Config) (*Conn, error) {
2020
var err error
21+
22+
if cfg.SCTPConfig == nil {
23+
cfg.SCTPConfig = &SCTPConfig{}
24+
}
25+
cfg.SCTPConfig.sctpInfo = &sctp.SndRcvInfo{PPID: 0x03000000, Stream: 0}
26+
2127
conn := &Conn{
2228
muState: new(sync.RWMutex),
2329
mode: modeClient,
2430
stateChan: make(chan State),
2531
established: make(chan struct{}),
26-
sctpInfo: &sctp.SndRcvInfo{PPID: 0x03000000, Stream: 0},
2732
cfg: cfg,
2833
}
2934

@@ -36,22 +41,22 @@ func Dial(ctx context.Context, net string, laddr, raddr *sctp.SCTPAddr, cfg *Con
3641
return nil, fmt.Errorf("invalid network: %s", net)
3742
}
3843

39-
conn.sctpConn, err = sctp.DialSCTP(n, laddr, raddr)
44+
conn.cfg.SCTPConfig.sctpConn, err = sctp.DialSCTP(n, laddr, raddr)
4045
if err != nil {
4146
return nil, err
4247
}
4348

44-
if conn.cfg.SctpSackInfo != nil && conn.cfg.SctpSackInfo.Enabled {
45-
err = conn.sctpConn.SetSackTimer(&sctp.SackTimer{
46-
SackDelay: conn.cfg.SctpSackInfo.SackDelay,
47-
SackFrequency: conn.cfg.SctpSackInfo.SackFrequency,
49+
if conn.cfg.SCTPConfig.SctpSackInfo != nil && conn.cfg.SCTPConfig.SctpSackInfo.Enabled {
50+
err = conn.cfg.SCTPConfig.sctpConn.SetSackTimer(&sctp.SackTimer{
51+
SackDelay: conn.cfg.SCTPConfig.SctpSackInfo.SackDelay,
52+
SackFrequency: conn.cfg.SCTPConfig.SctpSackInfo.SackFrequency,
4853
})
4954
if err != nil {
5055
return nil, fmt.Errorf("failed to set sack timer: %w", err)
5156
}
5257
}
5358

54-
r, err := conn.sctpConn.GetStatus()
59+
r, err := conn.cfg.SCTPConfig.sctpConn.GetStatus()
5560
if err != nil {
5661
return nil, fmt.Errorf("failed to get sctpConn status: %w", err)
5762
}
@@ -65,12 +70,12 @@ func Dial(ctx context.Context, net string, laddr, raddr *sctp.SCTPAddr, cfg *Con
6570
select {
6671
case _, ok := <-conn.established:
6772
if !ok {
68-
conn.sctpConn.Close()
73+
conn.cfg.SCTPConfig.sctpConn.Close()
6974
return nil, ErrFailedToEstablish
7075
}
7176
return conn, nil
7277
case <-time.After(10 * time.Second):
73-
conn.sctpConn.Close()
78+
conn.cfg.SCTPConfig.sctpConn.Close()
7479
return nil, ErrTimeout
7580
}
7681
}

config.go

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package m3ua
77
import (
88
"time"
99

10+
"github.com/ishidawataru/sctp"
1011
"github.com/wmnsk/go-m3ua/messages/params"
1112
)
1213

@@ -18,6 +19,13 @@ type HeartbeatInfo struct {
1819
Data []byte
1920
}
2021

22+
// NewHeartbeatInfo creates a new HeartbeatInfo.
23+
func NewHeartbeatInfo(interval, timer time.Duration, data []byte) *HeartbeatInfo {
24+
return &HeartbeatInfo{
25+
Enabled: true, Interval: interval, Timer: timer, Data: data,
26+
}
27+
}
28+
2129
// SctpSackInfo is a set of information for SCTP SACK timer configuration.
2230
//
2331
// SackDelay sack_delay: This parameter contains the number of milliseconds the
@@ -35,17 +43,20 @@ type SctpSackInfo struct {
3543
SackFrequency uint32
3644
}
3745

38-
// NewHeartbeatInfo creates a new HeartbeatInfo.
39-
func NewHeartbeatInfo(interval, timer time.Duration, data []byte) *HeartbeatInfo {
40-
return &HeartbeatInfo{
41-
Enabled: true, Interval: interval, Timer: timer, Data: data,
42-
}
46+
// SCTPConfig holds all SCTP-related configuration parameters.
47+
// This separates SCTP layer configuration from M3UA layer configuration.
48+
type SCTPConfig struct {
49+
*SctpSackInfo
50+
// sctpConn is the underlying SCTP association
51+
sctpConn *sctp.SCTPConn
52+
// sctpInfo is SndRcvInfo in SCTP association
53+
sctpInfo *sctp.SndRcvInfo
4354
}
4455

4556
// Config is a configuration that defines a M3UA server.
4657
type Config struct {
4758
*HeartbeatInfo
48-
*SctpSackInfo
59+
*SCTPConfig
4960
AspIdentifier *params.Param
5061
TrafficModeType *params.Param
5162
NetworkAppearance *params.Param
@@ -101,7 +112,10 @@ func (c *Config) EnableHeartbeat(interval, timer time.Duration) *Config {
101112
//
102113
// Note: sackDelay=0, sackFrequency=1 (disables delayed SACK)
103114
func (c *Config) SetSackConfig(sackDelay, sackFrequency uint32) *Config {
104-
c.SctpSackInfo = &SctpSackInfo{
115+
if c.SCTPConfig == nil {
116+
c.SCTPConfig = &SCTPConfig{}
117+
}
118+
c.SCTPConfig.SctpSackInfo = &SctpSackInfo{
105119
Enabled: true,
106120
SackDelay: sackDelay,
107121
SackFrequency: sackFrequency,

conn.go

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const (
2323
modeServer
2424
)
2525

26-
// Conn represents a M3UA connection, which satisfies standard net.Conn interface.
26+
// Conn represents a M3UA connection, which satisfies the standard net.Conn interface.
2727
type Conn struct {
2828
// maxMessageStreamID is the maximum negotiated sctp stream ID used,
2929
// must not be zero, must vary from 1 to maxMessageStreamID
@@ -40,15 +40,11 @@ type Conn struct {
4040
established chan struct{}
4141
// beatAckChan notifies that heartbeat gets the ack as expected
4242
beatAckChan chan struct{}
43-
// dataChan is to pass the ProtocolDataPayload(=payload on M3UA DATA) to user
43+
// dataChan is to pass the ProtocolDataPayload(=payload on M3UA DATA) to the user
4444
dataChan chan *params.ProtocolDataPayload
45-
// errChan is to pass errors to goroutine that monitors status
45+
// errChan is to pass errors to a goroutine that monitors status
4646
errChan chan error
47-
// sctpConn is the underlying SCTP association
48-
sctpConn *sctp.SCTPConn
49-
// sctpInfo is SndRcvInfo in SCTP association
50-
sctpInfo *sctp.SndRcvInfo
51-
// cfg is a configuration that is required to communicate between M3UA endpoints
47+
// cfg is a configuration required to communicate between M3UA endpoints
5248
cfg *Config
5349
// Condition to allow heartbeat, only after the state is AspUp
5450
beatAllow *sync.Cond
@@ -126,9 +122,9 @@ func (c *Conn) WriteToStream(b []byte, streamID uint16) (n int, err error) {
126122
}
127123

128124
// taken by value to avoid race condition on the stream id
129-
info := *c.sctpInfo
125+
info := *c.cfg.SCTPConfig.sctpInfo
130126
info.Stream = streamID
131-
n, err = c.sctpConn.SCTPWrite(d, &info)
127+
n, err = c.cfg.SCTPConfig.sctpConn.SCTPWrite(d, &info)
132128
if err != nil {
133129
return 0, err
134130
}
@@ -160,9 +156,9 @@ func (c *Conn) WritePDToStream(protocolData *params.Param, streamID uint16) (n i
160156
}
161157

162158
// taken by value to avoid race condition on the stream id
163-
info := *c.sctpInfo
159+
info := *c.cfg.SCTPConfig.sctpInfo
164160
info.Stream = streamID
165-
n, err = c.sctpConn.SCTPWrite(d, &info)
161+
n, err = c.cfg.SCTPConfig.sctpConn.SCTPWrite(d, &info)
166162
if err != nil {
167163
return 0, err
168164
}
@@ -180,12 +176,12 @@ func (c *Conn) WriteSignal(m3 messages.M3UA) (n int, err error) {
180176
}
181177

182178
// taken by value to avoid race condition on the stream id
183-
sctpInfo := *c.sctpInfo
179+
sctpInfo := *c.cfg.SCTPConfig.sctpInfo
184180
if m3.MessageClass() != messages.MsgClassTransfer {
185181
sctpInfo.Stream = 0
186182
}
187183

188-
nn, err := c.sctpConn.SCTPWrite(buf, &sctpInfo)
184+
nn, err := c.cfg.SCTPConfig.sctpConn.SCTPWrite(buf, &sctpInfo)
189185
if err != nil {
190186
return 0, fmt.Errorf("failed to write M3UA: %w", err)
191187
}
@@ -200,39 +196,39 @@ func (c *Conn) Close() error {
200196
defer c.muState.Unlock()
201197

202198
if c.state == StateAspDown {
203-
return c.sctpConn.Close()
199+
return c.cfg.SCTPConfig.sctpConn.Close()
204200
}
205201

206202
close(c.established)
207203
close(c.beatAckChan)
208204
close(c.dataChan)
209205
c.state = StateAspDown
210-
return c.sctpConn.Close()
206+
return c.cfg.SCTPConfig.sctpConn.Close()
211207
}
212208

213209
// LocalAddr returns the local network address.
214210
func (c *Conn) LocalAddr() net.Addr {
215-
return c.sctpConn.LocalAddr()
211+
return c.cfg.SCTPConfig.sctpConn.LocalAddr()
216212
}
217213

218214
// RemoteAddr returns the remote network address.
219215
func (c *Conn) RemoteAddr() net.Addr {
220-
return c.sctpConn.RemoteAddr()
216+
return c.cfg.SCTPConfig.sctpConn.RemoteAddr()
221217
}
222218

223219
// SetDeadline sets the read and write deadlines associated.
224220
func (c *Conn) SetDeadline(t time.Time) error {
225-
return c.sctpConn.SetDeadline(t)
221+
return c.cfg.SCTPConfig.sctpConn.SetDeadline(t)
226222
}
227223

228224
// SetReadDeadline sets the deadline for future Read calls.
229225
func (c *Conn) SetReadDeadline(t time.Time) error {
230-
return c.sctpConn.SetReadDeadline(t)
226+
return c.cfg.SCTPConfig.sctpConn.SetReadDeadline(t)
231227
}
232228

233229
// SetWriteDeadline sets the deadline for future Write calls.
234230
func (c *Conn) SetWriteDeadline(t time.Time) error {
235-
return c.sctpConn.SetWriteDeadline(t)
231+
return c.cfg.SCTPConfig.sctpConn.SetWriteDeadline(t)
236232
}
237233

238234
// State returns current state of Conn.
@@ -244,7 +240,7 @@ func (c *Conn) State() State {
244240

245241
// StreamID returns sctpInfo.Stream of Conn.
246242
func (c *Conn) StreamID() uint16 {
247-
return c.sctpInfo.Stream
243+
return c.cfg.SCTPConfig.sctpInfo.Stream
248244
}
249245

250246
// MaxMessageStreamID returns the maximum negotiated sctp stream ID
@@ -264,7 +260,7 @@ func (c *Conn) MaxMessageStreamID() uint16 {
264260
//
265261
// Note: sackDelay=0, sackFrequency=1 (disables delayed SACK)
266262
func (c *Conn) SetSctpSackConfig(sackDelay, sackFrequency uint32) error {
267-
return c.sctpConn.SetSackTimer(&sctp.SackTimer{
263+
return c.cfg.SCTPConfig.sctpConn.SetSackTimer(&sctp.SackTimer{
268264
SackDelay: sackDelay,
269265
SackFrequency: sackFrequency,
270266
})

fsm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func (c *Conn) monitor(ctx context.Context) {
226226
}
227227

228228
// Read from conn to see something coming from the peer.
229-
n, _, err := c.sctpConn.SCTPRead(buf)
229+
n, _, err := c.cfg.SCTPConfig.sctpConn.SCTPRead(buf)
230230
if err != nil {
231231
c.Close()
232232
return

server.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,12 +41,17 @@ func Listen(net string, laddr *sctp.SCTPAddr, cfg *Config) (*Listener, error) {
4141
// After successfully establishing the association with peer, Payload can be read with Read() func.
4242
// Other signals are automatically handled background in another goroutine.
4343
func (l *Listener) Accept(ctx context.Context) (*Conn, error) {
44+
45+
if l.Config.SCTPConfig == nil {
46+
l.Config.SCTPConfig = &SCTPConfig{}
47+
}
48+
l.Config.SCTPConfig.sctpInfo = &sctp.SndRcvInfo{PPID: 0x03000000, Stream: 0}
49+
4450
conn := &Conn{
4551
muState: new(sync.RWMutex),
4652
mode: modeServer,
4753
stateChan: make(chan State),
4854
established: make(chan struct{}),
49-
sctpInfo: &sctp.SndRcvInfo{PPID: 0x03000000, Stream: 0},
5055
cfg: l.Config,
5156
}
5257

@@ -60,23 +65,23 @@ func (l *Listener) Accept(ctx context.Context) (*Conn, error) {
6065
}
6166

6267
var ok bool
63-
conn.sctpConn, ok = c.(*sctp.SCTPConn)
68+
conn.cfg.SCTPConfig.sctpConn, ok = c.(*sctp.SCTPConn)
6469
if !ok {
6570
c.Close()
6671
return nil, fmt.Errorf("failed to assert server connection")
6772
}
6873

69-
if conn.cfg.SctpSackInfo != nil && conn.cfg.SctpSackInfo.Enabled {
70-
err = conn.sctpConn.SetSackTimer(&sctp.SackTimer{
71-
SackDelay: conn.cfg.SctpSackInfo.SackDelay,
72-
SackFrequency: conn.cfg.SctpSackInfo.SackFrequency,
74+
if conn.cfg.SCTPConfig.SctpSackInfo != nil && conn.cfg.SCTPConfig.SctpSackInfo.Enabled {
75+
err = conn.cfg.SCTPConfig.sctpConn.SetSackTimer(&sctp.SackTimer{
76+
SackDelay: conn.cfg.SCTPConfig.SctpSackInfo.SackDelay,
77+
SackFrequency: conn.cfg.SCTPConfig.SctpSackInfo.SackFrequency,
7378
})
7479
if err != nil {
7580
return nil, fmt.Errorf("failed to set sack timer: %w", err)
7681
}
7782
}
7883

79-
r, err := conn.sctpConn.GetStatus()
84+
r, err := conn.cfg.SCTPConfig.sctpConn.GetStatus()
8085
if err != nil {
8186
return nil, fmt.Errorf("failed to get sctpConn status: %w", err)
8287
}
@@ -90,12 +95,12 @@ func (l *Listener) Accept(ctx context.Context) (*Conn, error) {
9095
select {
9196
case _, ok := <-conn.established:
9297
if !ok {
93-
conn.sctpConn.Close()
98+
conn.cfg.SCTPConfig.sctpConn.Close()
9499
return nil, ErrFailedToEstablish
95100
}
96101
return conn, nil
97102
case <-time.After(10 * time.Second):
98-
conn.sctpConn.Close()
103+
conn.cfg.SCTPConfig.sctpConn.Close()
99104
return nil, ErrTimeout
100105
}
101106
}

0 commit comments

Comments
 (0)