Skip to content

Commit

Permalink
Unmarshal packets only once
Browse files Browse the repository at this point in the history
Unmarshal of a packet should only be done once, since doing
it multiple times ends up in an incorrect list of chunks.
Also, perform checksum validation first.
For pion, the only chunks requiring a correct CRC32c are the
INIT and COOKIE-ECHO chunks, which need to be the first
chunk in a packet.
  • Loading branch information
tuexen authored and edaniels committed Feb 28, 2024
1 parent 8cfa15d commit a5583a6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 23 deletions.
15 changes: 1 addition & 14 deletions association.go
Original file line number Diff line number Diff line change
Expand Up @@ -645,22 +645,9 @@ func (a *Association) marshalPacket(p *packet) ([]byte, error) {

func (a *Association) unmarshalPacket(raw []byte) (*packet, error) {
p := &packet{}
if !a.useZeroChecksum {
if err := p.unmarshal(true, raw); err != nil {
return nil, err
}
return p, nil
}

if err := p.unmarshal(false, raw); err != nil {
if err := p.unmarshal(!a.useZeroChecksum, raw); err != nil {
return nil, err
}
if chunkMandatoryChecksum(p.chunks) {
if err := p.unmarshal(true, raw); err != nil {
return nil, err
}
}

return p, nil
}

Expand Down
29 changes: 20 additions & 9 deletions packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,30 @@ func (p *packet) unmarshal(doChecksum bool, raw []byte) error {
return fmt.Errorf("%w: raw only %d bytes, %d is the minimum length", ErrPacketRawTooSmall, len(raw), packetHeaderSize)
}

offset := packetHeaderSize

// Check if doing CRC32c is required.
// Without having SCTP AUTH implemented, this depends only on the type
// og the first chunk.
if offset+chunkHeaderSize <= len(raw) {
switch chunkType(raw[offset]) {
case ctInit, ctCookieEcho:
doChecksum = true
default:
}
}
theirChecksum := binary.LittleEndian.Uint32(raw[8:])
if theirChecksum != 0 || doChecksum {
ourChecksum := generatePacketChecksum(raw)
if theirChecksum != ourChecksum {
return fmt.Errorf("%w: %d ours: %d", ErrChecksumMismatch, theirChecksum, ourChecksum)
}
}

p.sourcePort = binary.BigEndian.Uint16(raw[0:])
p.destinationPort = binary.BigEndian.Uint16(raw[2:])
p.verificationTag = binary.BigEndian.Uint32(raw[4:])

offset := packetHeaderSize
for {
// Exact match, no more chunks
if offset == len(raw) {
Expand Down Expand Up @@ -126,14 +145,6 @@ func (p *packet) unmarshal(doChecksum bool, raw []byte) error {
offset += chunkHeaderSize + c.valueLength() + chunkValuePadding
}

theirChecksum := binary.LittleEndian.Uint32(raw[8:])
if theirChecksum != 0 || doChecksum {
ourChecksum := generatePacketChecksum(raw)
if theirChecksum != ourChecksum {
return fmt.Errorf("%w: %d ours: %d", ErrChecksumMismatch, theirChecksum, ourChecksum)
}
}

return nil
}

Expand Down

0 comments on commit a5583a6

Please sign in to comment.