diff options
Diffstat (limited to 'vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go')
-rw-r--r-- | vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go b/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go new file mode 100644 index 0000000..cb8a100 --- /dev/null +++ b/vendor/github.com/pion/dtls/v2/pkg/protocol/handshake/message_client_hello.go @@ -0,0 +1,125 @@ +package handshake + +import ( + "encoding/binary" + + "github.com/pion/dtls/v2/pkg/protocol" + "github.com/pion/dtls/v2/pkg/protocol/extension" +) + +/* +MessageClientHello is for when a client first connects to a server it is +required to send the client hello as its first message. The client can also send a +client hello in response to a hello request or on its own +initiative in order to renegotiate the security parameters in an +existing connection. +*/ +type MessageClientHello struct { + Version protocol.Version + Random Random + Cookie []byte + + CipherSuiteIDs []uint16 + CompressionMethods []*protocol.CompressionMethod + Extensions []extension.Extension +} + +const handshakeMessageClientHelloVariableWidthStart = 34 + +// Type returns the Handshake Type +func (m MessageClientHello) Type() Type { + return TypeClientHello +} + +// Marshal encodes the Handshake +func (m *MessageClientHello) Marshal() ([]byte, error) { + if len(m.Cookie) > 255 { + return nil, errCookieTooLong + } + + out := make([]byte, handshakeMessageClientHelloVariableWidthStart) + out[0] = m.Version.Major + out[1] = m.Version.Minor + + rand := m.Random.MarshalFixed() + copy(out[2:], rand[:]) + + out = append(out, 0x00) // SessionID + + out = append(out, byte(len(m.Cookie))) + out = append(out, m.Cookie...) + out = append(out, encodeCipherSuiteIDs(m.CipherSuiteIDs)...) + out = append(out, protocol.EncodeCompressionMethods(m.CompressionMethods)...) + + extensions, err := extension.Marshal(m.Extensions) + if err != nil { + return nil, err + } + + return append(out, extensions...), nil +} + +// Unmarshal populates the message from encoded data +func (m *MessageClientHello) Unmarshal(data []byte) error { + if len(data) < 2+RandomLength { + return errBufferTooSmall + } + + m.Version.Major = data[0] + m.Version.Minor = data[1] + + var random [RandomLength]byte + copy(random[:], data[2:]) + m.Random.UnmarshalFixed(random) + + // rest of packet has variable width sections + currOffset := handshakeMessageClientHelloVariableWidthStart + currOffset += int(data[currOffset]) + 1 // SessionID + + currOffset++ + if len(data) <= currOffset { + return errBufferTooSmall + } + n := int(data[currOffset-1]) + if len(data) <= currOffset+n { + return errBufferTooSmall + } + m.Cookie = append([]byte{}, data[currOffset:currOffset+n]...) + currOffset += len(m.Cookie) + + // Cipher Suites + if len(data) < currOffset { + return errBufferTooSmall + } + cipherSuiteIDs, err := decodeCipherSuiteIDs(data[currOffset:]) + if err != nil { + return err + } + m.CipherSuiteIDs = cipherSuiteIDs + if len(data) < currOffset+2 { + return errBufferTooSmall + } + currOffset += int(binary.BigEndian.Uint16(data[currOffset:])) + 2 + + // Compression Methods + if len(data) < currOffset { + return errBufferTooSmall + } + compressionMethods, err := protocol.DecodeCompressionMethods(data[currOffset:]) + if err != nil { + return err + } + m.CompressionMethods = compressionMethods + if len(data) < currOffset { + return errBufferTooSmall + } + currOffset += int(data[currOffset]) + 1 + + // Extensions + extensions, err := extension.Unmarshal(data[currOffset:]) + if err != nil { + return err + } + m.Extensions = extensions + return nil +} |