mirror of
				https://github.com/bjdgyc/anylink.git
				synced 2025-11-01 00:59:34 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			112 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			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
 | |
| }
 |