diff options
Diffstat (limited to 'vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go')
-rw-r--r-- | vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go | 99 |
1 files changed, 99 insertions, 0 deletions
diff --git a/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go b/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go new file mode 100644 index 0000000..67e5a72 --- /dev/null +++ b/vendor/github.com/pion/dtls/v2/pkg/protocol/recordlayer/recordlayer.go @@ -0,0 +1,99 @@ +package recordlayer + +import ( + "encoding/binary" + + "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v2/pkg/protocol/alert" + "github.com/pion/dtls/v2/pkg/protocol/handshake" +) + +// RecordLayer which handles all data transport. +// The record layer is assumed to sit directly on top of some +// reliable transport such as TCP. The record layer can carry four types of content: +// +// 1. Handshake messages—used for algorithm negotiation and key establishment. +// 2. ChangeCipherSpec messages—really part of the handshake but technically a separate kind of message. +// 3. Alert messages—used to signal that errors have occurred +// 4. Application layer data +// +// The DTLS record layer is extremely similar to that of TLS 1.1. The +// only change is the inclusion of an explicit sequence number in the +// record. This sequence number allows the recipient to correctly +// verify the TLS MAC. +// +// https://tools.ietf.org/html/rfc4347#section-4.1 +type RecordLayer struct { + Header Header + Content protocol.Content +} + +// Marshal encodes the RecordLayer to binary +func (r *RecordLayer) Marshal() ([]byte, error) { + contentRaw, err := r.Content.Marshal() + if err != nil { + return nil, err + } + + r.Header.ContentLen = uint16(len(contentRaw)) + r.Header.ContentType = r.Content.ContentType() + + headerRaw, err := r.Header.Marshal() + if err != nil { + return nil, err + } + + return append(headerRaw, contentRaw...), nil +} + +// Unmarshal populates the RecordLayer from binary +func (r *RecordLayer) Unmarshal(data []byte) error { + if len(data) < HeaderSize { + return errBufferTooSmall + } + if err := r.Header.Unmarshal(data); err != nil { + return err + } + + switch protocol.ContentType(data[0]) { + case protocol.ContentTypeChangeCipherSpec: + r.Content = &protocol.ChangeCipherSpec{} + case protocol.ContentTypeAlert: + r.Content = &alert.Alert{} + case protocol.ContentTypeHandshake: + r.Content = &handshake.Handshake{} + case protocol.ContentTypeApplicationData: + r.Content = &protocol.ApplicationData{} + default: + return errInvalidContentType + } + + return r.Content.Unmarshal(data[HeaderSize:]) +} + +// UnpackDatagram extracts all RecordLayer messages from a single datagram. +// Note that as with TLS, multiple handshake messages may be placed in +// the same DTLS record, provided that there is room and that they are +// part of the same flight. Thus, there are two acceptable ways to pack +// two DTLS messages into the same datagram: in the same record or in +// separate records. +// https://tools.ietf.org/html/rfc6347#section-4.2.3 +func UnpackDatagram(buf []byte) ([][]byte, error) { + out := [][]byte{} + + for offset := 0; len(buf) != offset; { + if len(buf)-offset <= HeaderSize { + return nil, errInvalidPacketLength + } + + pktLen := (HeaderSize + int(binary.BigEndian.Uint16(buf[offset+11:]))) + if offset+pktLen > len(buf) { + return nil, errInvalidPacketLength + } + + out = append(out, buf[offset:offset+pktLen]) + offset += pktLen + } + + return out, nil +} |