@@ -11,6 +11,7 @@ type QuicError struct {
 	ErrorMessage       string
 	isTimeout          bool
 	isApplicationError bool
+	delayed            bool
 }
 
 var _ net.Error = &QuicError{}
package qerr

import (
	"fmt"
	"net"
)

// A QuicError consists of an error code plus a error reason
type QuicError struct {
	ErrorCode          ErrorCode
	ErrorMessage       string
	isTimeout          bool
	isApplicationError bool
}

var _ net.Error = &QuicError{}

// Error creates a new QuicError instance
func Error(errorCode ErrorCode, errorMessage string) *QuicError {
	return &QuicError{
		ErrorCode:    errorCode,
		ErrorMessage: errorMessage,
	}
}

// TimeoutError creates a new QuicError instance for a timeout error
func TimeoutError(errorMessage string) *QuicError {
	return &QuicError{
		ErrorMessage: errorMessage,
		isTimeout:    true,
	}
}

// CryptoError create a new QuicError instance for a crypto error
func CryptoError(tlsAlert uint8, errorMessage string) *QuicError {
	return &QuicError{
		ErrorCode:    0x100 + ErrorCode(tlsAlert),
		ErrorMessage: errorMessage,
	}
}

func ApplicationError(errorCode ErrorCode, errorMessage string) *QuicError {
	return &QuicError{
		ErrorCode:          errorCode,
		ErrorMessage:       errorMessage,
		isApplicationError: true,
	}
}

func (e *QuicError) Error() string {
	if e.isApplicationError {
		if len(e.ErrorMessage) == 0 {
			return fmt.Sprintf("Application error %#x", uint64(e.ErrorCode))
		}
		return fmt.Sprintf("Application error %#x: %s", uint64(e.ErrorCode), e.ErrorMessage)
	}
	if len(e.ErrorMessage) == 0 {
		return e.ErrorCode.Error()
	}
	return fmt.Sprintf("%s: %s", e.ErrorCode.String(), e.ErrorMessage)
}

// IsCryptoError says if this error is a crypto error
func (e *QuicError) IsCryptoError() bool {
	return e.ErrorCode.isCryptoError()
}

// Temporary says if the error is temporary.
func (e *QuicError) Temporary() bool {
	return false
}

// Timeout says if this error is a timeout.
func (e *QuicError) Timeout() bool {
	return e.isTimeout
}

// ToQuicError converts an arbitrary error to a QuicError. It leaves QuicErrors
// unchanged, and properly handles `ErrorCode`s.
func ToQuicError(err error) *QuicError {
	switch e := err.(type) {
	case *QuicError:
		return e
	case ErrorCode:
		return Error(e, "")
	}
	return Error(InternalError, err.Error())
}

It looks like this is only ever true for (1) remote close before handshake completes and (2) version negotiation failure. I propose we replace "delay" with "isInsecureClose" or similar throughout. I think that would be clearer.