mirror of
https://github.com/ziglang/zig.git
synced 2024-11-27 15:42:49 +00:00
os: usingnamespace fixes for std.x.os.Socket and std.os.TCP
Extract existing constants to do with TCP socket options into a 'TCP' namespace. Export 'MSG' and 'TCP' from std.os.{linux, windows} into std.c. Fix compile errors to do with std.x.os.Socket methods related to setting TCP socket options. Handle errors in the case that an interface could not be resolved in an IPv6 address on Windows. Tested using Wine with the loopback interface disabled. Have all instantiations of std.x.os.Socket on Windows instantiate an overlapped socket descriptor. Fixes the '1ms read timeout' test in std.x.net.tcp.Client. The test would previously deadlock, as read timeouts only apply to overlapped sockets. Windows documentation by default recommends that most instantiations of sockets on Windows be overlapped sockets (s.t. they may operate in both blocking or nonblocking mode when operated with WSA* syscalls). Refer to the documentation for WSASocketA for more info.
This commit is contained in:
parent
2118566931
commit
c4f97d3365
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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});
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user