diff --git a/lib/std/c/linux.zig b/lib/std/c/linux.zig index aa9d4087c2..b0760e9afe 100644 --- a/lib/std/c/linux.zig +++ b/lib/std/c/linux.zig @@ -31,6 +31,7 @@ pub const MAP = struct { pub const FAILED = @intToPtr(*c_void, maxInt(usize)); }; pub const MMAP2_UNIT = linux.MMAP2_UNIT; +pub const MSG = linux.MSG; pub const NAME_MAX = linux.NAME_MAX; pub const O = linux.O; pub const PATH_MAX = linux.PATH_MAX; @@ -54,6 +55,7 @@ pub const STDIN_FILENO = linux.STDIN_FILENO; pub const STDOUT_FILENO = linux.STDOUT_FILENO; pub const SYS = linux.SYS; pub const Sigaction = linux.Sigaction; +pub const TCP = linux.TCP; pub const VDSO = linux.VDSO; pub const W = linux.W; pub const W_OK = linux.W_OK; diff --git a/lib/std/c/windows.zig b/lib/std/c/windows.zig index 00cec5f5f7..1566e820fd 100644 --- a/lib/std/c/windows.zig +++ b/lib/std/c/windows.zig @@ -204,7 +204,9 @@ pub const in_addr = u32; pub const addrinfo = ws2_32.addrinfo; pub const AF = ws2_32.AF; +pub const MSG = ws2_32.MSG; pub const SOCK = ws2_32.SOCK; +pub const TCP = ws2_32.TCP; pub const IPPROTO = ws2_32.IPPROTO; pub const BTHPROTO_RFCOMM = ws2_32.BTHPROTO_RFCOMM; @@ -214,7 +216,6 @@ pub const POLL = ws2_32.POLL; pub const SOL = ws2_32.SOL; pub const SO = ws2_32.SO; pub const PVD_CONFIG = ws2_32.PVD_CONFIG; -pub const TCP_NODELAY = ws2_32.TCP_NODELAY; pub const O = struct { pub const RDONLY = 0o0; diff --git a/lib/std/os.zig b/lib/std/os.zig index d2a76989e1..5a4828286d 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -115,6 +115,7 @@ pub const SYS = system.SYS; pub const Sigaction = system.Sigaction; pub const Stat = system.Stat; pub const TCSA = system.TCSA; +pub const TCP = system.TCP; pub const VDSO = system.VDSO; pub const W = system.W; pub const addrinfo = system.addrinfo; diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index a5f49cda1c..df7166a4ff 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -2007,6 +2007,82 @@ pub const SOCK = struct { pub const NONBLOCK = if (is_mips) 0o200 else 0o4000; }; +pub const TCP = struct { + /// Turn off Nagle's algorithm + pub const NODELAY = 1; + /// Limit MSS + pub const MAXSEG = 2; + /// Never send partially complete segments. + pub const CORK = 3; + /// Start keeplives after this period, in seconds + pub const KEEPIDLE = 4; + /// Interval between keepalives + pub const KEEPINTVL = 5; + /// Number of keepalives before death + pub const KEEPCNT = 6; + /// Number of SYN retransmits + pub const SYNCNT = 7; + /// Life time of orphaned FIN-WAIT-2 state + pub const LINGER2 = 8; + /// Wake up listener only when data arrive + pub const DEFER_ACCEPT = 9; + /// Bound advertised window + pub const WINDOW_CLAMP = 10; + /// Information about this connection. + pub const INFO = 11; + /// Block/reenable quick acks + pub const QUICKACK = 12; + /// Congestion control algorithm + pub const CONGESTION = 13; + /// TCP MD5 Signature (RFC2385) + pub const MD5SIG = 14; + /// Use linear timeouts for thin streams + pub const THIN_LINEAR_TIMEOUTS = 16; + /// Fast retrans. after 1 dupack + pub const THIN_DUPACK = 17; + /// How long for loss retry before timeout + pub const USER_TIMEOUT = 18; + /// TCP sock is under repair right now + pub const REPAIR = 19; + pub const REPAIR_QUEUE = 20; + pub const QUEUE_SEQ = 21; + pub const REPAIR_OPTIONS = 22; + /// Enable FastOpen on listeners + pub const FASTOPEN = 23; + pub const TIMESTAMP = 24; + /// limit number of unsent bytes in write queue + pub const NOTSENT_LOWAT = 25; + /// Get Congestion Control (optional) info + pub const CC_INFO = 26; + /// Record SYN headers for new connections + pub const SAVE_SYN = 27; + /// Get SYN headers recorded for connection + pub const SAVED_SYN = 28; + /// Get/set window parameters + pub const REPAIR_WINDOW = 29; + /// Attempt FastOpen with connect + pub const FASTOPEN_CONNECT = 30; + /// Attach a ULP to a TCP connection + pub const ULP = 31; + /// TCP MD5 Signature with extensions + pub const MD5SIG_EXT = 32; + /// Set the key for Fast Open (cookie) + pub const FASTOPEN_KEY = 33; + /// Enable TFO without a TFO cookie + pub const FASTOPEN_NO_COOKIE = 34; + pub const ZEROCOPY_RECEIVE = 35; + /// Notify bytes available to read as a cmsg on read + pub const INQ = 36; + pub const CM_INQ = INQ; + /// delay outgoing packets by XX usec + pub const TX_DELAY = 37; + + pub const REPAIR_ON = 1; + pub const REPAIR_OFF = 0; + /// Turn off without window probes + pub const REPAIR_OFF_NO_WP = -1; +}; + pub const PF = struct { pub const UNSPEC = 0; pub const LOCAL = 1; @@ -3606,80 +3682,6 @@ pub const RR = struct { pub const AAAA = 28; }; -/// Turn off Nagle's algorithm -pub const TCP_NODELAY = 1; -/// Limit MSS -pub const TCP_MAXSEG = 2; -/// Never send partially complete segments. -pub const TCP_CORK = 3; -/// Start keeplives after this period, in seconds -pub const TCP_KEEPIDLE = 4; -/// Interval between keepalives -pub const TCP_KEEPINTVL = 5; -/// Number of keepalives before death -pub const TCP_KEEPCNT = 6; -/// Number of SYN retransmits -pub const TCP_SYNCNT = 7; -/// Life time of orphaned FIN-WAIT-2 state -pub const TCP_LINGER2 = 8; -/// Wake up listener only when data arrive -pub const TCP_DEFER_ACCEPT = 9; -/// Bound advertised window -pub const TCP_WINDOW_CLAMP = 10; -/// Information about this connection. -pub const TCP_INFO = 11; -/// Block/reenable quick acks -pub const TCP_QUICKACK = 12; -/// Congestion control algorithm -pub const TCP_CONGESTION = 13; -/// TCP MD5 Signature (RFC2385) -pub const TCP_MD5SIG = 14; -/// Use linear timeouts for thin streams -pub const TCP_THIN_LINEAR_TIMEOUTS = 16; -/// Fast retrans. after 1 dupack -pub const TCP_THIN_DUPACK = 17; -/// How long for loss retry before timeout -pub const TCP_USER_TIMEOUT = 18; -/// TCP sock is under repair right now -pub const TCP_REPAIR = 19; -pub const TCP_REPAIR_QUEUE = 20; -pub const TCP_QUEUE_SEQ = 21; -pub const TCP_REPAIR_OPTIONS = 22; -/// Enable FastOpen on listeners -pub const TCP_FASTOPEN = 23; -pub const TCP_TIMESTAMP = 24; -/// limit number of unsent bytes in write queue -pub const TCP_NOTSENT_LOWAT = 25; -/// Get Congestion Control (optional) info -pub const TCP_CC_INFO = 26; -/// Record SYN headers for new connections -pub const TCP_SAVE_SYN = 27; -/// Get SYN headers recorded for connection -pub const TCP_SAVED_SYN = 28; -/// Get/set window parameters -pub const TCP_REPAIR_WINDOW = 29; -/// Attempt FastOpen with connect -pub const TCP_FASTOPEN_CONNECT = 30; -/// Attach a ULP to a TCP connection -pub const TCP_ULP = 31; -/// TCP MD5 Signature with extensions -pub const TCP_MD5SIG_EXT = 32; -/// Set the key for Fast Open (cookie) -pub const TCP_FASTOPEN_KEY = 33; -/// Enable TFO without a TFO cookie -pub const TCP_FASTOPEN_NO_COOKIE = 34; -pub const TCP_ZEROCOPY_RECEIVE = 35; -/// Notify bytes available to read as a cmsg on read -pub const TCP_INQ = 36; -pub const TCP_CM_INQ = TCP_INQ; -/// delay outgoing packets by XX usec -pub const TCP_TX_DELAY = 37; - -pub const TCP_REPAIR_ON = 1; -pub const TCP_REPAIR_OFF = 0; -/// Turn off without window probes -pub const TCP_REPAIR_OFF_NO_WP = -1; - pub const tcp_repair_opt = extern struct { opt_code: u32, opt_val: u32, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index 247ae20deb..a4ada49bb8 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -442,27 +442,33 @@ pub const PROTECTION_LEVEL_EDGERESTRICTED = 20; pub const PROTECTION_LEVEL_RESTRICTED = 30; pub const INET_ADDRSTRLEN = 22; pub const INET6_ADDRSTRLEN = 65; -pub const TCP_OFFLOAD_NO_PREFERENCE = 0; -pub const TCP_OFFLOAD_NOT_PREFERRED = 1; -pub const TCP_OFFLOAD_PREFERRED = 2; -pub const TCP_EXPEDITED_1122 = 2; -pub const TCP_KEEPALIVE = 3; -pub const TCP_MAXSEG = 4; -pub const TCP_MAXRT = 5; -pub const TCP_STDURG = 6; -pub const TCP_NOURG = 7; -pub const TCP_ATMARK = 8; -pub const TCP_NOSYNRETRIES = 9; -pub const TCP_TIMESTAMPS = 10; -pub const TCP_OFFLOAD_PREFERENCE = 11; -pub const TCP_CONGESTION_ALGORITHM = 12; -pub const TCP_DELAY_FIN_ACK = 13; -pub const TCP_MAXRTMS = 14; -pub const TCP_FASTOPEN = 15; -pub const TCP_KEEPCNT = 16; -pub const TCP_KEEPINTVL = 17; -pub const TCP_FAIL_CONNECT_ON_ICMP_ERROR = 18; -pub const TCP_ICMP_ERROR_INFO = 19; + +pub const TCP = struct { + pub const NODELAY = 1; + pub const EXPEDITED_1122 = 2; + pub const OFFLOAD_NO_PREFERENCE = 0; + pub const OFFLOAD_NOT_PREFERRED = 1; + pub const OFFLOAD_PREFERRED = 2; + pub const KEEPALIVE = 3; + pub const MAXSEG = 4; + pub const MAXRT = 5; + pub const STDURG = 6; + pub const NOURG = 7; + pub const ATMARK = 8; + pub const NOSYNRETRIES = 9; + pub const TIMESTAMPS = 10; + pub const OFFLOAD_PREFERENCE = 11; + pub const CONGESTION_ALGORITHM = 12; + pub const DELAY_FIN_ACK = 13; + pub const MAXRTMS = 14; + pub const FASTOPEN = 15; + pub const KEEPCNT = 16; + pub const KEEPINTVL = 17; + pub const FAIL_CONNECT_ON_ICMP_ERROR = 18; + pub const ICMP_ERROR_INFO = 19; + pub const BSDURGENT = 28672; +}; + pub const UDP_SEND_MSG_SIZE = 2; pub const UDP_RECV_MAX_COALESCED_SIZE = 3; pub const UDP_COALESCED_INFO = 3; @@ -578,7 +584,6 @@ pub const SO = struct { }; pub const WSK_SO_BASE = 16384; -pub const TCP_NODELAY = 1; pub const IOC_UNIX = 0; pub const IOC_WS2 = 134217728; pub const IOC_PROTOCOL = 268435456; @@ -846,7 +851,6 @@ pub const POLL = struct { pub const NVAL = 4; }; -pub const TCP_BSDURGENT = 28672; pub const TF_DISCONNECT = 1; pub const TF_REUSE_SOCKET = 2; pub const TF_WRITE_BEHIND = 4; diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig index 4fbd07e00c..04cfd487e4 100644 --- a/lib/std/x/net/tcp.zig +++ b/lib/std/x/net/tcp.zig @@ -195,7 +195,7 @@ pub const Client = struct { pub fn setNoDelay(self: Client, enabled: bool) !void { if (@hasDecl(os.TCP, "NODELAY")) { const bytes = mem.asBytes(&@as(usize, @boolToInt(enabled))); - return self.socket.setOption(os.IPPROTO.TCP, os.TCP_NODELAY, bytes); + return self.socket.setOption(os.IPPROTO.TCP, os.TCP.NODELAY, bytes); } return error.UnsupportedSocketOption; } @@ -204,7 +204,7 @@ pub const Client = struct { /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK. pub fn setQuickACK(self: Client, enabled: bool) !void { if (@hasDecl(os.TCP, "QUICKACK")) { - return self.socket.setOption(os.IPPROTO.TCP, os.TCP_QUICKACK, mem.asBytes(&@as(u32, @boolToInt(enabled)))); + return self.socket.setOption(os.IPPROTO.TCP, os.TCP.QUICKACK, mem.asBytes(&@as(u32, @boolToInt(enabled)))); } return error.UnsupportedSocketOption; } @@ -305,7 +305,7 @@ pub const Listener = struct { /// support TCP Fast Open. pub fn setFastOpen(self: Listener, enabled: bool) !void { if (@hasDecl(os.TCP, "FASTOPEN")) { - return self.socket.setOption(os.IPPROTO.TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(u32, @boolToInt(enabled)))); + return self.socket.setOption(os.IPPROTO.TCP, os.TCP.FASTOPEN, mem.asBytes(&@as(u32, @boolToInt(enabled)))); } return error.UnsupportedSocketOption; } diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index 08ecede3e5..5b06d492a5 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -11,16 +11,20 @@ const have_ifnamesize = @hasDecl(os.system, "IFNAMESIZE"); /// Resolves a network interface name into a scope/zone ID. It returns /// an error if either resolution fails, or if the interface name is /// too long. -pub fn resolveScopeID(name: []const u8) !u32 { +pub fn resolveScopeId(name: []const u8) !u32 { if (have_ifnamesize) { - if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong; + if (name.len >= os.IFNAMESIZE) return error.NameTooLong; if (native_os.tag == .windows) { - var interface_name: [os.IFNAMESIZE]u8 = undefined; + var interface_name: [os.IFNAMESIZE:0]u8 = undefined; mem.copy(u8, &interface_name, name); interface_name[name.len] = 0; - return os.windows.ws2_32.if_nametoindex(@ptrCast([*:0]const u8, &interface_name)); + const rc = os.windows.ws2_32.if_nametoindex(@ptrCast([*:0]const u8, &interface_name)); + if (rc == 0) { + return error.InterfaceNotFound; + } + return rc; } const fd = try os.socket(os.AF.UNIX, os.SOCK.DGRAM, 0); @@ -35,7 +39,7 @@ pub fn resolveScopeID(name: []const u8) !u32 { return @bitCast(u32, f.ifru.ivalue); } - return error.Unsupported; + return error.InterfaceNotFound; } /// An IPv4 address comprised of 4 bytes. @@ -403,7 +407,8 @@ pub const IPv6 = extern struct { /// address. pub const ParseError = error{ MalformedV4Mapping, - BadScopeID, + InterfaceNotFound, + UnknownScopeId, } || IPv4.ParseError; /// Parses an arbitrary IPv6 address, including link-local addresses. @@ -412,12 +417,15 @@ pub const IPv6 = extern struct { const ip_slice = buf[0..index]; const scope_id_slice = buf[index + 1 ..]; - if (scope_id_slice.len == 0) return error.BadScopeID; + if (scope_id_slice.len == 0) return error.UnknownScopeId; const scope_id: u32 = switch (scope_id_slice[0]) { '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10), - else => resolveScopeID(scope_id_slice), - } catch return error.BadScopeID; + else => resolveScopeId(scope_id_slice) catch |err| switch (err) { + error.InterfaceNotFound => return error.InterfaceNotFound, + else => err, + }, + } catch return error.UnknownScopeId; return parseWithScopeID(ip_slice, scope_id); } @@ -568,6 +576,11 @@ test "ipv6: parse & format addresses with scope ids" { }; for (inputs) |input, i| { - try testing.expectFmt(outputs[i], "{}", .{try IPv6.parse(input)}); + const parsed = IPv6.parse(input) catch |err| switch (err) { + error.InterfaceNotFound => continue, + else => return err, + }; + + try testing.expectFmt(outputs[i], "{}", .{parsed}); } } diff --git a/lib/std/x/os/socket_windows.zig b/lib/std/x/os/socket_windows.zig index 178109dade..dc6d27c050 100644 --- a/lib/std/x/os/socket_windows.zig +++ b/lib/std/x/os/socket_windows.zig @@ -11,7 +11,7 @@ pub fn Mixin(comptime Socket: type) type { return struct { /// Open a new socket. pub fn init(domain: u32, socket_type: u32, protocol: u32, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Socket { - var raw_flags: u32 = 0; + var raw_flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED; const set = std.EnumSet(Socket.InitFlags).init(flags); if (set.contains(.close_on_exec)) raw_flags |= ws2_32.WSA_FLAG_NO_HANDLE_INHERIT;