mirror of https://github.com/bjdgyc/anylink.git
131 lines
3.2 KiB
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
|
|
}
|