func (f *fragmentBuffer) push(buf []byte) (bool, error) {
	frag := new(fragment)
	if err := frag.recordLayerHeader.Unmarshal(buf); err != nil {
		return false, err
	}
	if frag.recordLayerHeader.contentType != contentTypeHandshake {
		return false, nil
	}
	if err := frag.handshakeHeader.Unmarshal(buf[recordLayerHeaderSize:]); err != nil {
		return false, err
	}
	if _, ok := f.cache[frag.handshakeHeader.messageSequence]; !ok {
		f.cache[frag.handshakeHeader.messageSequence] = []*fragment{}
	}
	frag.data = append([]byte{}, buf[recordLayerHeaderSize+handshakeHeaderLength:]...)
	f.cache[frag.handshakeHeader.messageSequence] = append(f.cache[frag.handshakeHeader.messageSequence], frag)
	return true, nil
}
Attempts to push a DTLS packet to the fragmentBuffer
when it returns true it means the fragmentBuffer has inserted and the buffer shouldn't be handled
when an error returns it is fatal, and the DTLS connection should be stopped
package dtls
type fragment struct {
	recordLayerHeader recordLayerHeader
	handshakeHeader   handshakeHeader
	data              []byte
}
type fragmentBuffer struct {
	cache map[uint16][]*fragment
	currentMessageSequenceNumber uint16
}
func newFragmentBuffer() *fragmentBuffer {
	return &fragmentBuffer{cache: map[uint16][]*fragment{}}
}