From 8d86194b6e31788263d2cbdd03e2a8cde4134c37 Mon Sep 17 00:00:00 2001 From: Nameless Date: Mon, 6 Mar 2023 20:11:56 -0600 Subject: [PATCH] add error sets to tcpConnect* and tls.Client.init --- lib/std/crypto/tls/Client.zig | 50 ++++++++++++++++++++++++++++++++++- lib/std/net.zig | 34 +++++++++++++++++++++--- 2 files changed, 80 insertions(+), 4 deletions(-) diff --git a/lib/std/crypto/tls/Client.zig b/lib/std/crypto/tls/Client.zig index 627ad7ea59..01bf957820 100644 --- a/lib/std/crypto/tls/Client.zig +++ b/lib/std/crypto/tls/Client.zig @@ -88,11 +88,59 @@ pub const StreamInterface = struct { } }; +pub fn InitError(comptime Stream: type) type { + return std.mem.Allocator.Error || Stream.WriteError || Stream.ReadError || error { + InsufficientEntropy, + DiskQuota, + LockViolation, + NotOpenForWriting, + TlsAlert, + TlsUnexpectedMessage, + TlsIllegalParameter, + TlsDecryptFailure, + TlsRecordOverflow, + TlsBadRecordMac, + CertificateFieldHasInvalidLength, + CertificateHostMismatch, + CertificatePublicKeyInvalid, + CertificateExpired, + CertificateFieldHasWrongDataType, + CertificateIssuerMismatch, + CertificateNotYetValid, + CertificateSignatureAlgorithmMismatch, + CertificateSignatureAlgorithmUnsupported, + CertificateSignatureInvalid, + CertificateSignatureInvalidLength, + CertificateSignatureNamedCurveUnsupported, + CertificateSignatureUnsupportedBitCount, + TlsCertificateNotVerified, + TlsBadSignatureScheme, + TlsBadRsaSignatureBitCount, + InvalidEncoding, + IdentityElement, + SignatureVerificationFailed, + TlsDecryptError, + TlsConnectionTruncated, + TlsDecodeError, + UnsupportedCertificateVersion, + CertificateTimeInvalid, + CertificateHasUnrecognizedObjectId, + CertificateHasInvalidBitString, + MessageTooLong, + NegativeIntoUnsigned, + TargetTooSmall, + BufferTooSmall, + InvalidSignature, + NotSquare, + NonCanonical, + }; +} + /// Initiates a TLS handshake and establishes a TLSv1.3 session with `stream`, which /// must conform to `StreamInterface`. /// /// `host` is only borrowed during this function call. -pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) !Client { +pub fn init(stream: anytype, ca_bundle: Certificate.Bundle, host: []const u8) InitError(@TypeOf(stream))!Client { const host_len = @intCast(u16, host.len); var random_buffer: [128]u8 = undefined; diff --git a/lib/std/net.zig b/lib/std/net.zig index 50a0f8b9d7..cf112cbab9 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -702,8 +702,10 @@ pub const AddressList = struct { } }; +pub const TcpConnectToHostError = GetAddressListError || TcpConnectToAddressError; + /// All memory allocated with `allocator` will be freed before this function returns. -pub fn tcpConnectToHost(allocator: mem.Allocator, name: []const u8, port: u16) !Stream { +pub fn tcpConnectToHost(allocator: mem.Allocator, name: []const u8, port: u16) TcpConnectToHostError!Stream { const list = try getAddressList(allocator, name, port); defer list.deinit(); @@ -720,7 +722,9 @@ pub fn tcpConnectToHost(allocator: mem.Allocator, name: []const u8, port: u16) ! return std.os.ConnectError.ConnectionRefused; } -pub fn tcpConnectToAddress(address: Address) !Stream { +pub const TcpConnectToAddressError = std.os.SocketError || std.os.ConnectError; + +pub fn tcpConnectToAddress(address: Address) TcpConnectToAddressError!Stream { const nonblock = if (std.io.is_async) os.SOCK.NONBLOCK else 0; const sock_flags = os.SOCK.STREAM | nonblock | (if (builtin.target.os.tag == .windows) 0 else os.SOCK.CLOEXEC); @@ -737,8 +741,32 @@ pub fn tcpConnectToAddress(address: Address) !Stream { return Stream{ .handle = sockfd }; } +const GetAddressListError = std.mem.Allocator.Error || std.fs.File.OpenError || std.fs.File.ReadError || std.os.SocketError || std.os.BindError || error { + // TODO: break this up into error sets from the various underlying functions + + TemporaryNameServerFailure, + NameServerFailure, + AddressFamilyNotSupported, + UnknownHostName, + ServiceUnavailable, + Unexpected, + + HostLacksNetworkAddresses, + + InvalidCharacter, + InvalidEnd, + NonCanonical, + Overflow, + Incomplete, + InvalidIpv4Mapping, + InvalidIPAddressFormat, + + InterfaceNotFound, + FileSystem, +}; + /// Call `AddressList.deinit` on the result. -pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) !*AddressList { +pub fn getAddressList(allocator: mem.Allocator, name: []const u8, port: u16) GetAddressListError!*AddressList { const result = blk: { var arena = std.heap.ArenaAllocator.init(allocator); errdefer arena.deinit();