// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

package dtls

import (
	

	
	
	
	
	
	
)

func flight1Parse( context.Context,  flightConn,  *State,  *handshakeCache,  *handshakeConfig) (flightVal, *alert.Alert, error) {
	// HelloVerifyRequest can be skipped by the server,
	// so allow ServerHello during flight1 also
	, ,  := .fullPullMap(.handshakeRecvSequence, .cipherSuite,
		handshakeCachePullRule{handshake.TypeHelloVerifyRequest, .initialEpoch, false, true},
		handshakeCachePullRule{handshake.TypeServerHello, .initialEpoch, false, true},
	)
	if ! {
		// No valid message received. Keep reading
		return 0, nil, nil
	}

	if ,  := [handshake.TypeServerHello];  {
		// Flight1 and flight2 were skipped.
		// Parse as flight3.
		return flight3Parse(, , , , )
	}

	if ,  := [handshake.TypeHelloVerifyRequest].(*handshake.MessageHelloVerifyRequest);  {
		// DTLS 1.2 clients must not assume that the server will use the protocol version
		// specified in HelloVerifyRequest message. RFC 6347 Section 4.2.1
		if !.Version.Equal(protocol.Version1_0) && !.Version.Equal(protocol.Version1_2) {
			return 0, &alert.Alert{Level: alert.Fatal, Description: alert.ProtocolVersion}, errUnsupportedProtocolVersion
		}
		.cookie = append([]byte{}, .Cookie...)
		.handshakeRecvSequence = 
		return flight3, nil, nil
	}

	return 0, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, nil
}

func flight1Generate( flightConn,  *State,  *handshakeCache,  *handshakeConfig) ([]*packet, *alert.Alert, error) {
	var  uint16
	.localEpoch.Store()
	.remoteEpoch.Store()
	.namedCurve = defaultNamedCurve
	.cookie = nil

	if  := .localRandom.Populate();  != nil {
		return nil, nil, 
	}

	 := []extension.Extension{
		&extension.SupportedSignatureAlgorithms{
			SignatureHashAlgorithms: .localSignatureSchemes,
		},
		&extension.RenegotiationInfo{
			RenegotiatedConnection: 0,
		},
	}

	var  bool
	for ,  := range .localCipherSuites {
		if .ECC() {
			 = true
			break
		}
	}

	if  {
		 = append(, []extension.Extension{
			&extension.SupportedEllipticCurves{
				EllipticCurves: .ellipticCurves,
			},
			&extension.SupportedPointFormats{
				PointFormats: []elliptic.CurvePointFormat{elliptic.CurvePointFormatUncompressed},
			},
		}...)
	}

	if len(.localSRTPProtectionProfiles) > 0 {
		 = append(, &extension.UseSRTP{
			ProtectionProfiles: .localSRTPProtectionProfiles,
		})
	}

	if .extendedMasterSecret == RequestExtendedMasterSecret ||
		.extendedMasterSecret == RequireExtendedMasterSecret {
		 = append(, &extension.UseExtendedMasterSecret{
			Supported: true,
		})
	}

	if len(.serverName) > 0 {
		 = append(, &extension.ServerName{ServerName: .serverName})
	}

	if len(.supportedProtocols) > 0 {
		 = append(, &extension.ALPN{ProtocolNameList: .supportedProtocols})
	}

	if .sessionStore != nil {
		.log.Tracef("[handshake] try to resume session")
		if ,  := .sessionStore.Get(.sessionKey());  != nil {
			return nil, &alert.Alert{Level: alert.Fatal, Description: alert.InternalError}, 
		} else if .ID != nil {
			.log.Tracef("[handshake] get saved session: %x", .ID)

			.SessionID = .ID
			.masterSecret = .Secret
		}
	}

	return []*packet{
		{
			record: &recordlayer.RecordLayer{
				Header: recordlayer.Header{
					Version: protocol.Version1_2,
				},
				Content: &handshake.Handshake{
					Message: &handshake.MessageClientHello{
						Version:            protocol.Version1_2,
						SessionID:          .SessionID,
						Cookie:             .cookie,
						Random:             .localRandom,
						CipherSuiteIDs:     cipherSuiteIDs(.localCipherSuites),
						CompressionMethods: defaultCompressionMethods(),
						Extensions:         ,
					},
				},
			},
		},
	}, nil, nil
}