@@ -177,6 +177,8 @@ type Association struct {
177
177
cumulativeTSNAckPoint uint32
178
178
advancedPeerTSNAckPoint uint32
179
179
useForwardTSN bool
180
+ useZeroChecksum bool
181
+ requestZeroChecksum bool
180
182
181
183
// Congestion control parameters
182
184
maxReceiveBufferSize uint32
@@ -233,6 +235,7 @@ type Config struct {
233
235
NetConn net.Conn
234
236
MaxReceiveBufferSize uint32
235
237
MaxMessageSize uint32
238
+ EnableZeroChecksum bool
236
239
LoggerFactory logging.LoggerFactory
237
240
}
238
241
@@ -320,6 +323,7 @@ func createAssociation(config Config) *Association {
320
323
handshakeCompletedCh : make (chan error ),
321
324
cumulativeTSNAckPoint : tsn - 1 ,
322
325
advancedPeerTSNAckPoint : tsn - 1 ,
326
+ requestZeroChecksum : config .EnableZeroChecksum ,
323
327
silentError : ErrSilentlyDiscard ,
324
328
stats : & associationStats {},
325
329
log : config .LoggerFactory .NewLogger ("sctp" ),
@@ -362,6 +366,11 @@ func (a *Association) init(isClient bool) {
362
366
init .initiateTag = a .myVerificationTag
363
367
init .advertisedReceiverWindowCredit = a .maxReceiveBufferSize
364
368
setSupportedExtensions (& init .chunkInitCommon )
369
+
370
+ if a .requestZeroChecksum {
371
+ init .params = append (init .params , & paramZeroChecksumAcceptable {edmid : dtlsErrorDetectionMethod })
372
+ }
373
+
365
374
a .storedInit = init
366
375
367
376
err := a .sendInit ()
@@ -618,10 +627,45 @@ func (a *Association) unregisterStream(s *Stream, err error) {
618
627
s .readNotifier .Broadcast ()
619
628
}
620
629
630
+ func chunkMandatoryChecksum (cc []chunk ) bool {
631
+ for _ , c := range cc {
632
+ switch c .(type ) {
633
+ case * chunkInit , * chunkInitAck , * chunkCookieEcho :
634
+ return true
635
+ }
636
+ }
637
+ return false
638
+ }
639
+
640
+ func (a * Association ) marshalPacket (p * packet ) ([]byte , error ) {
641
+ return p .marshal (! a .useZeroChecksum || chunkMandatoryChecksum (p .chunks ))
642
+ }
643
+
644
+ func (a * Association ) unmarshalPacket (raw []byte ) (* packet , error ) {
645
+ p := & packet {}
646
+ if ! a .useZeroChecksum {
647
+ if err := p .unmarshal (true , raw ); err != nil {
648
+ return nil , err
649
+ }
650
+ return p , nil
651
+ }
652
+
653
+ if err := p .unmarshal (false , raw ); err != nil {
654
+ return nil , err
655
+ }
656
+ if chunkMandatoryChecksum (p .chunks ) {
657
+ if err := p .unmarshal (true , raw ); err != nil {
658
+ return nil , err
659
+ }
660
+ }
661
+
662
+ return p , nil
663
+ }
664
+
621
665
// handleInbound parses incoming raw packets
622
666
func (a * Association ) handleInbound (raw []byte ) error {
623
- p := & packet {}
624
- if err := p . unmarshal ( raw ); err != nil {
667
+ p , err := a . unmarshalPacket ( raw )
668
+ if err != nil {
625
669
a .log .Warnf ("[%s] unable to parse SCTP packet %s" , a .name , err )
626
670
return nil
627
671
}
@@ -647,7 +691,7 @@ func (a *Association) handleInbound(raw []byte) error {
647
691
// The caller should hold the lock
648
692
func (a * Association ) gatherDataPacketsToRetransmit (rawPackets [][]byte ) [][]byte {
649
693
for _ , p := range a .getDataPacketsToRetransmit () {
650
- raw , err := p . marshal ( )
694
+ raw , err := a . marshalPacket ( p )
651
695
if err != nil {
652
696
a .log .Warnf ("[%s] failed to serialize a DATA packet to be retransmitted" , a .name )
653
697
continue
@@ -668,7 +712,7 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte)
668
712
a .log .Tracef ("[%s] T3-rtx timer start (pt1)" , a .name )
669
713
a .t3RTX .start (a .rtoMgr .getRTO ())
670
714
for _ , p := range a .bundleDataChunksIntoPackets (chunks ) {
671
- raw , err := p . marshal ( )
715
+ raw , err := a . marshalPacket ( p )
672
716
if err != nil {
673
717
a .log .Warnf ("[%s] failed to serialize a DATA packet" , a .name )
674
718
continue
@@ -683,7 +727,7 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte)
683
727
a .log .Debugf ("[%s] retransmit %d RECONFIG chunk(s)" , a .name , len (a .reconfigs ))
684
728
for _ , c := range a .reconfigs {
685
729
p := a .createPacket ([]chunk {c })
686
- raw , err := p . marshal ( )
730
+ raw , err := a . marshalPacket ( p )
687
731
if err != nil {
688
732
a .log .Warnf ("[%s] failed to serialize a RECONFIG packet to be retransmitted" , a .name )
689
733
} else {
@@ -706,7 +750,7 @@ func (a *Association) gatherOutboundDataAndReconfigPackets(rawPackets [][]byte)
706
750
a .log .Debugf ("[%s] sending RECONFIG: rsn=%d tsn=%d streams=%v" ,
707
751
a .name , rsn , a .myNextTSN - 1 , sisToReset )
708
752
p := a .createPacket ([]chunk {c })
709
- raw , err := p . marshal ( )
753
+ raw , err := a . marshalPacket ( p )
710
754
if err != nil {
711
755
a .log .Warnf ("[%s] failed to serialize a RECONFIG packet to be transmitted" , a .name )
712
756
} else {
@@ -769,7 +813,7 @@ func (a *Association) gatherOutboundFastRetransmissionPackets(rawPackets [][]byt
769
813
}
770
814
771
815
if len (toFastRetrans ) > 0 {
772
- raw , err := a .createPacket (toFastRetrans ). marshal ( )
816
+ raw , err := a .marshalPacket ( a . createPacket (toFastRetrans ))
773
817
if err != nil {
774
818
a .log .Warnf ("[%s] failed to serialize a DATA packet to be fast-retransmitted" , a .name )
775
819
} else {
@@ -787,7 +831,7 @@ func (a *Association) gatherOutboundSackPackets(rawPackets [][]byte) [][]byte {
787
831
a .ackState = ackStateIdle
788
832
sack := a .createSelectiveAckChunk ()
789
833
a .log .Debugf ("[%s] sending SACK: %s" , a .name , sack )
790
- raw , err := a .createPacket ([]chunk {sack }). marshal ( )
834
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {sack }))
791
835
if err != nil {
792
836
a .log .Warnf ("[%s] failed to serialize a SACK packet" , a .name )
793
837
} else {
@@ -804,7 +848,7 @@ func (a *Association) gatherOutboundForwardTSNPackets(rawPackets [][]byte) [][]b
804
848
a .willSendForwardTSN = false
805
849
if sna32GT (a .advancedPeerTSNAckPoint , a .cumulativeTSNAckPoint ) {
806
850
fwdtsn := a .createForwardTSN ()
807
- raw , err := a .createPacket ([]chunk {fwdtsn }). marshal ( )
851
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {fwdtsn }))
808
852
if err != nil {
809
853
a .log .Warnf ("[%s] failed to serialize a Forward TSN packet" , a .name )
810
854
} else {
@@ -827,7 +871,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by
827
871
cumulativeTSNAck : a .cumulativeTSNAckPoint ,
828
872
}
829
873
830
- raw , err := a .createPacket ([]chunk {shutdown }). marshal ( )
874
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {shutdown }))
831
875
if err != nil {
832
876
a .log .Warnf ("[%s] failed to serialize a Shutdown packet" , a .name )
833
877
} else {
@@ -839,7 +883,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by
839
883
840
884
shutdownAck := & chunkShutdownAck {}
841
885
842
- raw , err := a .createPacket ([]chunk {shutdownAck }). marshal ( )
886
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {shutdownAck }))
843
887
if err != nil {
844
888
a .log .Warnf ("[%s] failed to serialize a ShutdownAck packet" , a .name )
845
889
} else {
@@ -851,7 +895,7 @@ func (a *Association) gatherOutboundShutdownPackets(rawPackets [][]byte) ([][]by
851
895
852
896
shutdownComplete := & chunkShutdownComplete {}
853
897
854
- raw , err := a .createPacket ([]chunk {shutdownComplete }). marshal ( )
898
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {shutdownComplete }))
855
899
if err != nil {
856
900
a .log .Warnf ("[%s] failed to serialize a ShutdownComplete packet" , a .name )
857
901
} else {
@@ -875,7 +919,7 @@ func (a *Association) gatherAbortPacket() ([]byte, error) {
875
919
abort .errorCauses = []errorCause {cause }
876
920
}
877
921
878
- raw , err := a .createPacket ([]chunk {abort }). marshal ( )
922
+ raw , err := a .marshalPacket ( a . createPacket ([]chunk {abort }))
879
923
880
924
return raw , err
881
925
}
@@ -900,7 +944,7 @@ func (a *Association) gatherOutbound() ([][]byte, bool) {
900
944
901
945
if a .controlQueue .size () > 0 {
902
946
for _ , p := range a .controlQueue .popAll () {
903
- raw , err := p . marshal ( )
947
+ raw , err := a . marshalPacket ( p )
904
948
if err != nil {
905
949
a .log .Warnf ("[%s] failed to serialize a control packet" , a .name )
906
950
continue
@@ -1092,6 +1136,7 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) {
1092
1136
// subtracting one from it.
1093
1137
a .peerLastTSN = i .initialTSN - 1
1094
1138
1139
+ peerHasZeroChecksum := false
1095
1140
for _ , param := range i .params {
1096
1141
switch v := param .(type ) { // nolint:gocritic
1097
1142
case * paramSupportedExtensions :
@@ -1101,8 +1146,11 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) {
1101
1146
a .useForwardTSN = true
1102
1147
}
1103
1148
}
1149
+ case * paramZeroChecksumAcceptable :
1150
+ peerHasZeroChecksum = v .edmid == dtlsErrorDetectionMethod
1104
1151
}
1105
1152
}
1153
+
1106
1154
if ! a .useForwardTSN {
1107
1155
a .log .Warnf ("[%s] not using ForwardTSN (on init)" , a .name )
1108
1156
}
@@ -1129,6 +1177,12 @@ func (a *Association) handleInit(p *packet, i *chunkInit) ([]*packet, error) {
1129
1177
1130
1178
initAck .params = []param {a .myCookie }
1131
1179
1180
+ if peerHasZeroChecksum {
1181
+ initAck .params = append (initAck .params , & paramZeroChecksumAcceptable {edmid : dtlsErrorDetectionMethod })
1182
+ a .useZeroChecksum = true
1183
+ }
1184
+ a .log .Debugf ("[%s] useZeroChecksum=%t (on init)" , a .name , a .useZeroChecksum )
1185
+
1132
1186
setSupportedExtensions (& initAck .chunkInitCommon )
1133
1187
1134
1188
outbound .chunks = []chunk {initAck }
@@ -1186,8 +1240,13 @@ func (a *Association) handleInitAck(p *packet, i *chunkInitAck) error {
1186
1240
a .useForwardTSN = true
1187
1241
}
1188
1242
}
1243
+ case * paramZeroChecksumAcceptable :
1244
+ a .useZeroChecksum = v .edmid == dtlsErrorDetectionMethod
1189
1245
}
1190
1246
}
1247
+
1248
+ a .log .Debugf ("[%s] useZeroChecksum=%t (on initAck)" , a .name , a .useZeroChecksum )
1249
+
1191
1250
if ! a .useForwardTSN {
1192
1251
a .log .Warnf ("[%s] not using ForwardTSN (on initAck)" , a .name )
1193
1252
}
0 commit comments