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

112 lines
2.7 KiB
Go

package handshake
import (
"encoding/binary"
"github.com/pion/dtls/v2/pkg/protocol"
"github.com/pion/dtls/v2/pkg/protocol/extension"
)
// MessageServerHello is sent in response to a ClientHello
// message when it was able to find an acceptable set of algorithms.
// If it cannot find such a match, it will respond with a handshake
// failure alert.
//
// https://tools.ietf.org/html/rfc5246#section-7.4.1.3
type MessageServerHello struct {
Version protocol.Version
Random Random
SessionID []byte // TODO 添加anylink支持
CipherSuiteID *uint16
CompressionMethod *protocol.CompressionMethod
Extensions []extension.Extension
}
const messageServerHelloVariableWidthStart = 2 + RandomLength
// Type returns the Handshake Type
func (m MessageServerHello) Type() Type {
return TypeServerHello
}
// Marshal encodes the Handshake
func (m *MessageServerHello) Marshal() ([]byte, error) {
if m.CipherSuiteID == nil {
return nil, errCipherSuiteUnset
} else if m.CompressionMethod == nil {
return nil, errCompressionMethodUnset
}
out := make([]byte, messageServerHelloVariableWidthStart)
out[0] = m.Version.Major
out[1] = m.Version.Minor
rand := m.Random.MarshalFixed()
copy(out[2:], rand[:])
// out = append(out, 0x00) // SessionID
// TODO 添加SessionID
out = append(out, byte(len(m.SessionID))) // SessionID
out = append(out, m.SessionID...)
out = append(out, []byte{0x00, 0x00}...)
binary.BigEndian.PutUint16(out[len(out)-2:], *m.CipherSuiteID)
out = append(out, byte(m.CompressionMethod.ID))
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 *MessageServerHello) 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)
currOffset := messageServerHelloVariableWidthStart
currOffset += int(data[currOffset]) + 1 // SessionID
if len(data) < (currOffset + 2) {
return errBufferTooSmall
}
m.CipherSuiteID = new(uint16)
*m.CipherSuiteID = binary.BigEndian.Uint16(data[currOffset:])
currOffset += 2
if len(data) < currOffset {
return errBufferTooSmall
}
if compressionMethod, ok := protocol.CompressionMethods()[protocol.CompressionMethodID(data[currOffset])]; ok {
m.CompressionMethod = compressionMethod
currOffset++
} else {
return errInvalidCompressionMethod
}
if len(data) <= currOffset {
m.Extensions = []extension.Extension{}
return nil
}
extensions, err := extension.Unmarshal(data[currOffset:])
if err != nil {
return err
}
m.Extensions = extensions
return nil
}