<commit_before>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

#if compiler(>=5.1) && compiler(<5.2)
@_implementationOnly import CNIOBoringSSL
#else
import CNIOBoringSSL
#endif

/// Wraps a single error from BoringSSL.
public struct BoringSSLInternalError: Equatable, CustomStringConvertible {
    let errorCode: UInt32

    var errorMessage: String? {
        // TODO(cory): This should become non-optional in the future, as it always succeeds.
        var scratchBuffer = [CChar](repeating: 0, count: 512)
        return scratchBuffer.withUnsafeMutableBufferPointer { pointer in
            CNIOBoringSSL_ERR_error_string_n(self.errorCode, pointer.baseAddress!, pointer.count)
            return String(cString: pointer.baseAddress!)
        }
    }

    public var description: String {
        return "Error: \(errorCode) \(errorMessage ?? "")"
    }

    init(errorCode: UInt32) {
        self.errorCode = errorCode
    }

    public static func ==(lhs: BoringSSLInternalError, rhs: BoringSSLInternalError) -> Bool {
        return lhs.errorCode == rhs.errorCode
    }

}

/// A representation of BoringSSL's internal error stack: a list of BoringSSL errors.
public typealias NIOBoringSSLErrorStack = [BoringSSLInternalError]


/// Errors that can be raised by NIO's BoringSSL wrapper.
public enum NIOSSLError: Error {
    case writeDuringTLSShutdown
    case unableToAllocateBoringSSLObject
    case noSuchFilesystemObject
    case failedToLoadCertificate
    case failedToLoadPrivateKey
    case handshakeFailed(BoringSSLError)
    case shutdownFailed(BoringSSLError)
    case cannotMatchULabel
    case noCertificateToValidate
    case unableToValidateCertificate
    case cannotFindPeerIP
    case readInInvalidTLSState
    case uncleanShutdown
}

extension NIOSSLError: Equatable {
    public static func ==(lhs: NIOSSLError, rhs: NIOSSLError) -> Bool {
        switch (lhs, rhs) {
        case (.writeDuringTLSShutdown, .writeDuringTLSShutdown),
             (.unableToAllocateBoringSSLObject, .unableToAllocateBoringSSLObject),
             (.noSuchFilesystemObject, .noSuchFilesystemObject),
             (.failedToLoadCertificate, .failedToLoadCertificate),
             (.failedToLoadPrivateKey, .failedToLoadPrivateKey),
             (.cannotMatchULabel, .cannotMatchULabel),
             (.noCertificateToValidate, .noCertificateToValidate),
             (.unableToValidateCertificate, .unableToValidateCertificate),
             (.uncleanShutdown, .uncleanShutdown):
            return true
        case (.handshakeFailed(let err1), .handshakeFailed(let err2)),
             (.shutdownFailed(let err1), .shutdownFailed(let err2)):
            return err1 == err2
        default:
            return false
        }
    }
}

/// Closing the TLS channel cleanly timed out, so it was closed uncleanly.
public struct NIOSSLCloseTimedOutError: Error {}

/// An enum that wraps individual BoringSSL errors directly.
public enum BoringSSLError: Error {
    case noError
    case zeroReturn
    case wantRead
    case wantWrite
    case wantConnect
    case wantAccept
    case wantX509Lookup
    case wantCertificateVerify
    case syscallError
    case sslError(NIOBoringSSLErrorStack)
    case unknownError(NIOBoringSSLErrorStack)
    case invalidSNIName(NIOBoringSSLErrorStack)
    case failedToSetALPN(NIOBoringSSLErrorStack)
}

extension BoringSSLError: Equatable {}

public func ==(lhs: BoringSSLError, rhs: BoringSSLError) -> Bool {
    switch (lhs, rhs) {
    case (.noError, .noError),
         (.zeroReturn, .zeroReturn),
         (.wantRead, .wantRead),
         (.wantWrite, .wantWrite),
         (.wantConnect, .wantConnect),
         (.wantAccept, .wantAccept),
         (.wantCertificateVerify, .wantCertificateVerify),
         (.wantX509Lookup, .wantX509Lookup),
         (.syscallError, .syscallError):
        return true
    case (.sslError(let e1), .sslError(let e2)),
         (.unknownError(let e1), .unknownError(let e2)):
        return e1 == e2
    default:
        return false
    }
}

internal extension BoringSSLError {
    static func fromSSLGetErrorResult(_ result: CInt) -> BoringSSLError? {
        switch result {
        case SSL_ERROR_NONE:
            return .noError
        case SSL_ERROR_ZERO_RETURN:
            return .zeroReturn
        case SSL_ERROR_WANT_READ:
            return .wantRead
        case SSL_ERROR_WANT_WRITE:
            return .wantWrite
        case SSL_ERROR_WANT_CONNECT:
            return .wantConnect
        case SSL_ERROR_WANT_ACCEPT:
            return .wantAccept
        case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
            return .wantCertificateVerify
        case SSL_ERROR_WANT_X509_LOOKUP:
            return .wantX509Lookup
        case SSL_ERROR_SYSCALL:<commit_msg>Add missing cases to == for NIOSSLError and BoringSSLError (#163)<commit_after>//===----------------------------------------------------------------------===//
//
// This source file is part of the SwiftNIO open source project
//
// Copyright (c) 2017-2018 Apple Inc. and the SwiftNIO project authors
// Licensed under Apache License v2.0
//
// See LICENSE.txt for license information
// See CONTRIBUTORS.txt for the list of SwiftNIO project authors
//
// SPDX-License-Identifier: Apache-2.0
//
//===----------------------------------------------------------------------===//

#if compiler(>=5.1) && compiler(<5.2)
@_implementationOnly import CNIOBoringSSL
#else
import CNIOBoringSSL
#endif

/// Wraps a single error from BoringSSL.
public struct BoringSSLInternalError: Equatable, CustomStringConvertible {
    let errorCode: UInt32

    var errorMessage: String? {
        // TODO(cory): This should become non-optional in the future, as it always succeeds.
        var scratchBuffer = [CChar](repeating: 0, count: 512)
        return scratchBuffer.withUnsafeMutableBufferPointer { pointer in
            CNIOBoringSSL_ERR_error_string_n(self.errorCode, pointer.baseAddress!, pointer.count)
            return String(cString: pointer.baseAddress!)
        }
    }

    public var description: String {
        return "Error: \(errorCode) \(errorMessage ?? "")"
    }

    init(errorCode: UInt32) {
        self.errorCode = errorCode
    }

    public static func ==(lhs: BoringSSLInternalError, rhs: BoringSSLInternalError) -> Bool {
        return lhs.errorCode == rhs.errorCode
    }

}

/// A representation of BoringSSL's internal error stack: a list of BoringSSL errors.
public typealias NIOBoringSSLErrorStack = [BoringSSLInternalError]


/// Errors that can be raised by NIO's BoringSSL wrapper.
public enum NIOSSLError: Error {
    case writeDuringTLSShutdown
    case unableToAllocateBoringSSLObject
    case noSuchFilesystemObject
    case failedToLoadCertificate
    case failedToLoadPrivateKey
    case handshakeFailed(BoringSSLError)
    case shutdownFailed(BoringSSLError)
    case cannotMatchULabel
    case noCertificateToValidate
    case unableToValidateCertificate
    case cannotFindPeerIP
    case readInInvalidTLSState
    case uncleanShutdown
}

extension NIOSSLError: Equatable {
    public static func ==(lhs: NIOSSLError, rhs: NIOSSLError) -> Bool {
        switch (lhs, rhs) {
        case (.writeDuringTLSShutdown, .writeDuringTLSShutdown),
             (.unableToAllocateBoringSSLObject, .unableToAllocateBoringSSLObject),
             (.noSuchFilesystemObject, .noSuchFilesystemObject),
             (.failedToLoadCertificate, .failedToLoadCertificate),
             (.failedToLoadPrivateKey, .failedToLoadPrivateKey),
             (.cannotMatchULabel, .cannotMatchULabel),
             (.noCertificateToValidate, .noCertificateToValidate),
             (.unableToValidateCertificate, .unableToValidateCertificate),
             (.cannotFindPeerIP, .cannotFindPeerIP),
             (.readInInvalidTLSState, .readInInvalidTLSState),
             (.uncleanShutdown, .uncleanShutdown):
            return true
        case (.handshakeFailed(let err1), .handshakeFailed(let err2)),
             (.shutdownFailed(let err1), .shutdownFailed(let err2)):
            return err1 == err2
        default:
            return false
        }
    }
}

/// Closing the TLS channel cleanly timed out, so it was closed uncleanly.
public struct NIOSSLCloseTimedOutError: Error {}

/// An enum that wraps individual BoringSSL errors directly.
public enum BoringSSLError: Error {
    case noError
    case zeroReturn
    case wantRead
    case wantWrite
    case wantConnect
    case wantAccept
    case wantX509Lookup
    case wantCertificateVerify
    case syscallError
    case sslError(NIOBoringSSLErrorStack)
    case unknownError(NIOBoringSSLErrorStack)
    case invalidSNIName(NIOBoringSSLErrorStack)
    case failedToSetALPN(NIOBoringSSLErrorStack)
}

extension BoringSSLError: Equatable {}

public func ==(lhs: BoringSSLError, rhs: BoringSSLError) -> Bool {
    switch (lhs, rhs) {
    case (.noError, .noError),
         (.zeroReturn, .zeroReturn),
         (.wantRead, .wantRead),
         (.wantWrite, .wantWrite),
         (.wantConnect, .wantConnect),
         (.wantAccept, .wantAccept),
         (.wantX509Lookup, .wantX509Lookup),
         (.wantCertificateVerify, .wantCertificateVerify),
         (.syscallError, .syscallError):
        return true
    case (.sslError(let e1), .sslError(let e2)),
         (.unknownError(let e1), .unknownError(let e2)),
         (.invalidSNIName(let e1), .invalidSNIName(let e2)),
         (.failedToSetALPN(let e1), .failedToSetALPN(let e2)):
        return e1 == e2
    default:
        return false
    }
}

internal extension BoringSSLError {
    static func fromSSLGetErrorResult(_ result: CInt) -> BoringSSLError? {
        switch result {
        case SSL_ERROR_NONE:
            return .noError
        case SSL_ERROR_ZERO_RETURN:
            return .zeroReturn
        case SSL_ERROR_WANT_READ:
            return .wantRead
        case SSL_ERROR_WANT_WRITE:
            return .wantWrite
        case SSL_ERROR_WANT_CONNECT:
            return .wantConnect
        case SSL_ERROR_WANT_ACCEPT:
            return .wantAccept
        case SSL_ERROR_WANT_CERTIFICATE_VERIFY:
            return .wantCertificateVerify
        case SSL_ERROR_WANT_X509_LOOKUP:
            return .wantX509Lookup
        case SSL_ERROR_SYSCALL:
{'fraction_non_alphanumeric': 0.10750980758453203, 'fraction_numerical': 0.010181206799925275, 'mean_word_length': 2.605050505050505, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5370509', 'n_tokens_mistral': 3195, 'n_tokens_neox': 2987, 'n_words': 767}