1package dtls 2 3import "encoding/binary" 4 5type recordLayerHeader struct { 6 contentType contentType 7 contentLen uint16 8 protocolVersion protocolVersion 9 epoch uint16 10 sequenceNumber uint64 // uint48 in spec 11 12} 13 14const ( 15 recordLayerHeaderSize = 13 16 maxSequenceNumber = 0x0000FFFFFFFFFFFF 17 18 dtls1_2Major = 0xfe 19 dtls1_2Minor = 0xfd 20) 21 22var protocolVersion1_2 = protocolVersion{dtls1_2Major, dtls1_2Minor} 23 24// https://tools.ietf.org/html/rfc4346#section-6.2.1 25type protocolVersion struct { 26 major, minor uint8 27} 28 29func (r *recordLayerHeader) Marshal() ([]byte, error) { 30 if r.sequenceNumber > maxSequenceNumber { 31 return nil, errSequenceNumberOverflow 32 } 33 34 out := make([]byte, recordLayerHeaderSize) 35 out[0] = byte(r.contentType) 36 out[1] = r.protocolVersion.major 37 out[2] = r.protocolVersion.minor 38 binary.BigEndian.PutUint16(out[3:], r.epoch) 39 putBigEndianUint48(out[5:], r.sequenceNumber) 40 binary.BigEndian.PutUint16(out[recordLayerHeaderSize-2:], r.contentLen) 41 return out, nil 42} 43 44func (r *recordLayerHeader) Unmarshal(data []byte) error { 45 if len(data) < recordLayerHeaderSize { 46 return errBufferTooSmall 47 } 48 r.contentType = contentType(data[0]) 49 r.protocolVersion.major = data[1] 50 r.protocolVersion.minor = data[2] 51 r.epoch = binary.BigEndian.Uint16(data[3:]) 52 53 // SequenceNumber is stored as uint48, make into uint64 54 seqCopy := make([]byte, 8) 55 copy(seqCopy[2:], data[5:11]) 56 r.sequenceNumber = binary.BigEndian.Uint64(seqCopy) 57 58 return nil 59} 60