You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
SCTP will lose data if a stream is closed 'too soon' after the last blocking write call.
The stream.Close() API does not flush transmission buffers before returning, nor is there any obvious way to manually flush a stream transmission buffer before calling Close(). As a result, any data stored for transmission will be lost, and "use of closed network connection" errors will result from lower layers of the communications stack, such as client.Shutdown(), and (udp)conn.Close().
Motivation
Data loss is a bad thing. SCTP should honor the implied intent of sctp.ReliabilityTypeReliable when terminating streams, by sending all pending data to the peer before closing the stream.
Describe alternatives you've considered
There does not seem to be any robust solution to conduct an orderly shutdown of a stream without cooperation from the peer to communicate that it has received all expected data.
Blocking until an OnBufferedAmountLow() handler reports 0 bytes in the send buffer only moves the issue down to the underlying transport. Closing a stream may succeed without error, but data will still be lost by lower layers of the stack and a "use of closed network connection" error will still result.
Example
Based on the pinger/ponger examples. Error checking removed for brevity.
Send:
func main() {
conn, err := net.Dial("udp", "127.0.0.1:9899")
config := sctp.Config{
NetConn: conn,
LoggerFactory: logging.NewDefaultLoggerFactory(),
BlockWrite: true,
}
a, err := sctp.Client(config)
stream, err := a.OpenStream(0, sctp.PayloadTypeWebRTCString)
stream.SetReliabilityParams(false, sctp.ReliabilityTypeReliable, 10)
const Size = 256
const Iter = (Size * 1024 * 1024) / 65536
// Sends 4096 blocks of 64KiB each.
for i := 0; i < Iter; i++ {
pingMsg := make([]byte, 65536)
rand.Read(pingMsg)
_, err = stream.Write([]byte(pingMsg))
}
// One of these (usually conn.Close()) will return a "use of closed network connection" error)
err = stream.Close()
if err != nil { log.Panic(err) }
err = a.Close()
if err != nil { log.Panic(err) }
err = conn.Close()
if err != nil { log.Panic(err) }
}
Summary
SCTP will lose data if a stream is closed 'too soon' after the last blocking write call.
The stream.Close() API does not flush transmission buffers before returning, nor is there any obvious way to manually flush a stream transmission buffer before calling Close(). As a result, any data stored for transmission will be lost, and "use of closed network connection" errors will result from lower layers of the communications stack, such as client.Shutdown(), and (udp)conn.Close().
Motivation
Data loss is a bad thing. SCTP should honor the implied intent of sctp.ReliabilityTypeReliable when terminating streams, by sending all pending data to the peer before closing the stream.
Describe alternatives you've considered
There does not seem to be any robust solution to conduct an orderly shutdown of a stream without cooperation from the peer to communicate that it has received all expected data.
Blocking until an OnBufferedAmountLow() handler reports 0 bytes in the send buffer only moves the issue down to the underlying transport. Closing a stream may succeed without error, but data will still be lost by lower layers of the stack and a "use of closed network connection" error will still result.
Example
Based on the pinger/ponger examples. Error checking removed for brevity.
Send:
Receive:
This code will typically stop, as a result of the send process ending, at block 4093 (zero-based count) out of 4094. Block 4094 will be lost.
The text was updated successfully, but these errors were encountered: