dockerfiles/anylink/dtls-2.0.9/pkg/protocol/handshake/message_client_hello.go

131 lines
3.2 KiB
Go

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
SessionID []byte // TODO 添加anylink支持
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
// TODO 添加SessionID
m.SessionID = data[handshakeMessageClientHelloVariableWidthStart+1 : currOffset]
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
}