| author | |
| committer | |
| log | 3a0e8c2b45e57e75cedd052b00fd7ae46def8383 |
| tree | de7fc435f56bf6484aa40fa41a0f8a1b5890c1bf |
| parent | 844eb932f4a253863d36e01a713724141c1f6361 |
| parent | 7f4667219339e92dc75e7dfd5f0078f229804567 |
| signature |
std: Add basic smoke test for net functionality8 files changed, 222 insertions(+), 48 deletions(-)
lib/std/c.zig+2-2| ... | ... | @@ -150,8 +150,8 @@ pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint |
| 150 | 150 | pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int; |
| 151 | 151 | pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int; |
| 152 | 152 | pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int; |
| 153 | pub extern "c" fn accept(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t) c_int; | |
| 154 | pub extern "c" fn accept4(sockfd: fd_t, addr: *sockaddr, addrlen: *socklen_t, flags: c_uint) c_int; | |
| 153 | pub extern "c" fn accept(sockfd: fd_t, addr: ?*sockaddr, addrlen: ?*socklen_t) c_int; | |
| 154 | pub extern "c" fn accept4(sockfd: fd_t, addr: ?*sockaddr, addrlen: ?*socklen_t, flags: c_uint) c_int; | |
| 155 | 155 | pub extern "c" fn getsockopt(sockfd: fd_t, level: u32, optname: u32, optval: ?*c_void, optlen: *socklen_t) c_int; |
| 156 | 156 | pub extern "c" fn setsockopt(sockfd: fd_t, level: u32, optname: u32, optval: ?*const c_void, optlen: socklen_t) c_int; |
| 157 | 157 | pub extern "c" fn send(sockfd: fd_t, buf: *const c_void, len: usize, flags: u32) isize; |
lib/std/net.zig+24-18| ... | ... | @@ -11,11 +11,7 @@ const mem = std.mem; |
| 11 | 11 | const os = std.os; |
| 12 | 12 | const fs = std.fs; |
| 13 | 13 | |
| 14 | test "" { | |
| 15 | _ = @import("net/test.zig"); | |
| 16 | } | |
| 17 | ||
| 18 | const has_unix_sockets = @hasDecl(os, "sockaddr_un"); | |
| 14 | pub const has_unix_sockets = @hasDecl(os, "sockaddr_un"); | |
| 19 | 15 | |
| 20 | 16 | pub const Address = extern union { |
| 21 | 17 | any: os.sockaddr, |
| ... | ... | @@ -610,7 +606,7 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { |
| 610 | 606 | os.SOCK_STREAM | os.SOCK_CLOEXEC | opt_non_block, |
| 611 | 607 | 0, |
| 612 | 608 | ); |
| 613 | errdefer os.close(sockfd); | |
| 609 | errdefer os.closeSocket(sockfd); | |
| 614 | 610 | |
| 615 | 611 | var addr = try std.net.Address.initUnix(path); |
| 616 | 612 | |
| ... | ... | @@ -629,7 +625,7 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { |
| 629 | 625 | fn if_nametoindex(name: []const u8) !u32 { |
| 630 | 626 | var ifr: os.ifreq = undefined; |
| 631 | 627 | var sockfd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM | os.SOCK_CLOEXEC, 0); |
| 632 | defer os.close(sockfd); | |
| 628 | defer os.closeSocket(sockfd); | |
| 633 | 629 | |
| 634 | 630 | std.mem.copy(u8, &ifr.ifrn.name, name); |
| 635 | 631 | ifr.ifrn.name[name.len] = 0; |
| ... | ... | @@ -677,7 +673,7 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { |
| 677 | 673 | const sock_flags = os.SOCK_STREAM | nonblock | |
| 678 | 674 | (if (builtin.os.tag == .windows) 0 else os.SOCK_CLOEXEC); |
| 679 | 675 | const sockfd = try os.socket(address.any.family, sock_flags, os.IPPROTO_TCP); |
| 680 | errdefer os.close(sockfd); | |
| 676 | errdefer os.closeSocket(sockfd); | |
| 681 | 677 | |
| 682 | 678 | if (std.io.is_async) { |
| 683 | 679 | const loop = std.event.Loop.instance orelse return error.WouldBlock; |
| ... | ... | @@ -912,7 +908,7 @@ fn linuxLookupName( |
| 912 | 908 | var prefixlen: i32 = 0; |
| 913 | 909 | const sock_flags = os.SOCK_DGRAM | os.SOCK_CLOEXEC; |
| 914 | 910 | if (os.socket(addr.addr.any.family, sock_flags, os.IPPROTO_UDP)) |fd| syscalls: { |
| 915 | defer os.close(fd); | |
| 911 | defer os.closeSocket(fd); | |
| 916 | 912 | os.connect(fd, da, dalen) catch break :syscalls; |
| 917 | 913 | key |= DAS_USABLE; |
| 918 | 914 | os.getsockname(fd, sa, &salen) catch break :syscalls; |
| ... | ... | @@ -1392,7 +1388,7 @@ fn resMSendRc( |
| 1392 | 1388 | }, |
| 1393 | 1389 | else => |e| return e, |
| 1394 | 1390 | }; |
| 1395 | defer os.close(fd); | |
| 1391 | defer os.closeSocket(fd); | |
| 1396 | 1392 | try os.bind(fd, &sa.any, sl); |
| 1397 | 1393 | |
| 1398 | 1394 | // Past this point, there are no errors. Each individual query will |
| ... | ... | @@ -1546,16 +1542,14 @@ fn dnsParseCallback(ctx: dpc_ctx, rr: u8, data: []const u8, packet: []const u8) |
| 1546 | 1542 | if (data.len != 4) return error.InvalidDnsARecord; |
| 1547 | 1543 | const new_addr = try ctx.addrs.addOne(); |
| 1548 | 1544 | new_addr.* = LookupAddr{ |
| 1549 | // TODO slice [0..4] to make this *[4]u8 without @ptrCast | |
| 1550 | .addr = Address.initIp4(@ptrCast(*const [4]u8, data.ptr).*, ctx.port), | |
| 1545 | .addr = Address.initIp4(data[0..4].*, ctx.port), | |
| 1551 | 1546 | }; |
| 1552 | 1547 | }, |
| 1553 | 1548 | os.RR_AAAA => { |
| 1554 | 1549 | if (data.len != 16) return error.InvalidDnsAAAARecord; |
| 1555 | 1550 | const new_addr = try ctx.addrs.addOne(); |
| 1556 | 1551 | new_addr.* = LookupAddr{ |
| 1557 | // TODO slice [0..16] to make this *[16]u8 without @ptrCast | |
| 1558 | .addr = Address.initIp6(@ptrCast(*const [16]u8, data.ptr).*, ctx.port, 0, 0), | |
| 1552 | .addr = Address.initIp6(data[0..16].*, ctx.port, 0, 0), | |
| 1559 | 1553 | }; |
| 1560 | 1554 | }, |
| 1561 | 1555 | os.RR_CNAME => { |
| ... | ... | @@ -1579,7 +1573,7 @@ pub const StreamServer = struct { |
| 1579 | 1573 | /// `undefined` until `listen` returns successfully. |
| 1580 | 1574 | listen_address: Address, |
| 1581 | 1575 | |
| 1582 | sockfd: ?os.fd_t, | |
| 1576 | sockfd: ?os.socket_t, | |
| 1583 | 1577 | |
| 1584 | 1578 | pub const Options = struct { |
| 1585 | 1579 | /// How many connections the kernel will accept on the application's behalf. |
| ... | ... | @@ -1616,13 +1610,13 @@ pub const StreamServer = struct { |
| 1616 | 1610 | const sockfd = try os.socket(address.any.family, sock_flags, proto); |
| 1617 | 1611 | self.sockfd = sockfd; |
| 1618 | 1612 | errdefer { |
| 1619 | os.close(sockfd); | |
| 1613 | os.closeSocket(sockfd); | |
| 1620 | 1614 | self.sockfd = null; |
| 1621 | 1615 | } |
| 1622 | 1616 | |
| 1623 | 1617 | if (self.reuse_address) { |
| 1624 | 1618 | try os.setsockopt( |
| 1625 | self.sockfd.?, | |
| 1619 | sockfd, | |
| 1626 | 1620 | os.SOL_SOCKET, |
| 1627 | 1621 | os.SO_REUSEADDR, |
| 1628 | 1622 | &mem.toBytes(@as(c_int, 1)), |
| ... | ... | @@ -1640,7 +1634,7 @@ pub const StreamServer = struct { |
| 1640 | 1634 | /// not listening. |
| 1641 | 1635 | pub fn close(self: *StreamServer) void { |
| 1642 | 1636 | if (self.sockfd) |fd| { |
| 1643 | os.close(fd); | |
| 1637 | os.closeSocket(fd); | |
| 1644 | 1638 | self.sockfd = null; |
| 1645 | 1639 | self.listen_address = undefined; |
| 1646 | 1640 | } |
| ... | ... | @@ -1670,6 +1664,14 @@ pub const StreamServer = struct { |
| 1670 | 1664 | /// Permission to create a socket of the specified type and/or |
| 1671 | 1665 | /// protocol is denied. |
| 1672 | 1666 | PermissionDenied, |
| 1667 | ||
| 1668 | FileDescriptorNotASocket, | |
| 1669 | ||
| 1670 | ConnectionResetByPeer, | |
| 1671 | ||
| 1672 | NetworkSubsystemFailed, | |
| 1673 | ||
| 1674 | OperationNotSupported, | |
| 1673 | 1675 | } || os.UnexpectedError; |
| 1674 | 1676 | |
| 1675 | 1677 | pub const Connection = struct { |
| ... | ... | @@ -1701,3 +1703,7 @@ pub const StreamServer = struct { |
| 1701 | 1703 | } |
| 1702 | 1704 | } |
| 1703 | 1705 | }; |
| 1706 | ||
| 1707 | test "" { | |
| 1708 | _ = @import("net/test.zig"); | |
| 1709 | } |
lib/std/net/test.zig+67-8| ... | ... | @@ -95,22 +95,81 @@ test "parse and render IPv4 addresses" { |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 97 | test "resolve DNS" { |
| 98 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 99 | ||
| 98 | 100 | if (std.builtin.os.tag == .windows) { |
| 99 | 101 | _ = try std.os.windows.WSAStartup(2, 2); |
| 100 | 102 | } |
| 101 | if (builtin.os.tag == .wasi) { | |
| 102 | // DNS resolution not implemented on Windows yet. | |
| 103 | return error.SkipZigTest; | |
| 103 | defer { | |
| 104 | if (std.builtin.os.tag == .windows) { | |
| 105 | std.os.windows.WSACleanup() catch unreachable; | |
| 106 | } | |
| 104 | 107 | } |
| 105 | 108 | |
| 106 | const address_list = net.getAddressList(testing.allocator, "example.com", 80) catch |err| switch (err) { | |
| 109 | // Resolve localhost, this should not fail. | |
| 110 | { | |
| 111 | const localhost_v4 = try net.Address.parseIp("127.0.0.1", 80); | |
| 112 | const localhost_v6 = try net.Address.parseIp("::2", 80); | |
| 113 | ||
| 114 | const result = try net.getAddressList(testing.allocator, "localhost", 80); | |
| 115 | defer result.deinit(); | |
| 116 | for (result.addrs) |addr| { | |
| 117 | if (addr.eql(localhost_v4) or addr.eql(localhost_v6)) break; | |
| 118 | } else @panic("unexpected address for localhost"); | |
| 119 | } | |
| 120 | ||
| 121 | { | |
| 107 | 122 | // The tests are required to work even when there is no Internet connection, |
| 108 | 123 | // so some of these errors we must accept and skip the test. |
| 109 | error.UnknownHostName => return error.SkipZigTest, | |
| 110 | error.TemporaryNameServerFailure => return error.SkipZigTest, | |
| 111 | else => return err, | |
| 124 | const result = net.getAddressList(testing.allocator, "example.com", 80) catch |err| switch (err) { | |
| 125 | error.UnknownHostName => return error.SkipZigTest, | |
| 126 | error.TemporaryNameServerFailure => return error.SkipZigTest, | |
| 127 | else => return err, | |
| 128 | }; | |
| 129 | result.deinit(); | |
| 130 | } | |
| 131 | } | |
| 132 | ||
| 133 | test "listen on a port, send bytes, receive bytes" { | |
| 134 | if (builtin.single_threaded) return error.SkipZigTest; | |
| 135 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 136 | ||
| 137 | if (std.builtin.os.tag == .windows) { | |
| 138 | _ = try std.os.windows.WSAStartup(2, 2); | |
| 139 | } | |
| 140 | defer { | |
| 141 | if (std.builtin.os.tag == .windows) { | |
| 142 | std.os.windows.WSACleanup() catch unreachable; | |
| 143 | } | |
| 144 | } | |
| 145 | ||
| 146 | // Try only the IPv4 variant as some CI builders have no IPv6 localhost | |
| 147 | // configured. | |
| 148 | const localhost = try net.Address.parseIp("127.0.0.1", 8080); | |
| 149 | ||
| 150 | var server = net.StreamServer.init(.{}); | |
| 151 | defer server.deinit(); | |
| 152 | ||
| 153 | try server.listen(localhost); | |
| 154 | ||
| 155 | const S = struct { | |
| 156 | fn clientFn(server_address: net.Address) !void { | |
| 157 | const socket = try net.tcpConnectToAddress(server_address); | |
| 158 | defer socket.close(); | |
| 159 | ||
| 160 | _ = try socket.writer().writeAll("Hello world!"); | |
| 161 | } | |
| 112 | 162 | }; |
| 113 | address_list.deinit(); | |
| 163 | ||
| 164 | const t = try std.Thread.spawn(server.listen_address, S.clientFn); | |
| 165 | defer t.wait(); | |
| 166 | ||
| 167 | var client = try server.accept(); | |
| 168 | var buf: [16]u8 = undefined; | |
| 169 | const n = try client.file.reader().read(&buf); | |
| 170 | ||
| 171 | testing.expectEqual(@as(usize, 12), n); | |
| 172 | testing.expectEqualSlices(u8, "Hello world!", buf[0..n]); | |
| 114 | 173 | } |
| 115 | 174 | |
| 116 | 175 | test "listen on a port, send bytes, receive bytes" { |
lib/std/os.zig+48-16| ... | ... | @@ -2687,6 +2687,14 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t |
| 2687 | 2687 | } |
| 2688 | 2688 | } |
| 2689 | 2689 | |
| 2690 | pub fn closeSocket(sock: socket_t) void { | |
| 2691 | if (builtin.os.tag == .windows) { | |
| 2692 | windows.closesocket(sock) catch unreachable; | |
| 2693 | } else { | |
| 2694 | close(sock); | |
| 2695 | } | |
| 2696 | } | |
| 2697 | ||
| 2690 | 2698 | pub const BindError = error{ |
| 2691 | 2699 | /// The address is protected, and the user is not the superuser. |
| 2692 | 2700 | /// For UNIX domain sockets: Search permission is denied on a component |
| ... | ... | @@ -2731,8 +2739,8 @@ pub const BindError = error{ |
| 2731 | 2739 | |
| 2732 | 2740 | /// addr is `*const T` where T is one of the sockaddr |
| 2733 | 2741 | pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!void { |
| 2734 | const rc = system.bind(sock, addr, len); | |
| 2735 | 2742 | if (builtin.os.tag == .windows) { |
| 2743 | const rc = windows.bind(sock, addr, len); | |
| 2736 | 2744 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 2737 | 2745 | switch (windows.ws2_32.WSAGetLastError()) { |
| 2738 | 2746 | .WSANOTINITIALISED => unreachable, // not initialized WSA |
| ... | ... | @@ -2750,6 +2758,7 @@ pub fn bind(sock: socket_t, addr: *const sockaddr, len: socklen_t) BindError!voi |
| 2750 | 2758 | } |
| 2751 | 2759 | return; |
| 2752 | 2760 | } else { |
| 2761 | const rc = system.bind(sock, addr, len); | |
| 2753 | 2762 | switch (errno(rc)) { |
| 2754 | 2763 | 0 => return, |
| 2755 | 2764 | EACCES => return error.AccessDenied, |
| ... | ... | @@ -2800,8 +2809,8 @@ const ListenError = error{ |
| 2800 | 2809 | } || UnexpectedError; |
| 2801 | 2810 | |
| 2802 | 2811 | pub fn listen(sock: socket_t, backlog: u31) ListenError!void { |
| 2803 | const rc = system.listen(sock, backlog); | |
| 2804 | 2812 | if (builtin.os.tag == .windows) { |
| 2813 | const rc = windows.listen(sock, backlog); | |
| 2805 | 2814 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 2806 | 2815 | switch (windows.ws2_32.WSAGetLastError()) { |
| 2807 | 2816 | .WSANOTINITIALISED => unreachable, // not initialized WSA |
| ... | ... | @@ -2818,6 +2827,7 @@ pub fn listen(sock: socket_t, backlog: u31) ListenError!void { |
| 2818 | 2827 | } |
| 2819 | 2828 | return; |
| 2820 | 2829 | } else { |
| 2830 | const rc = system.listen(sock, backlog); | |
| 2821 | 2831 | switch (errno(rc)) { |
| 2822 | 2832 | 0 => return, |
| 2823 | 2833 | EADDRINUSE => return error.AddressInUse, |
| ... | ... | @@ -2905,6 +2915,8 @@ pub fn accept( |
| 2905 | 2915 | const accepted_sock = while (true) { |
| 2906 | 2916 | const rc = if (have_accept4) |
| 2907 | 2917 | system.accept4(sock, addr, addr_size, flags) |
| 2918 | else if (builtin.os.tag == .windows) | |
| 2919 | windows.accept(sock, addr, addr_size) | |
| 2908 | 2920 | else |
| 2909 | 2921 | system.accept(sock, addr, addr_size); |
| 2910 | 2922 | |
| ... | ... | @@ -3077,8 +3089,8 @@ pub const GetSockNameError = error{ |
| 3077 | 3089 | } || UnexpectedError; |
| 3078 | 3090 | |
| 3079 | 3091 | pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void { |
| 3080 | const rc = system.getsockname(sock, addr, addrlen); | |
| 3081 | 3092 | if (builtin.os.tag == .windows) { |
| 3093 | const rc = windows.getsockname(sock, addr, addrlen); | |
| 3082 | 3094 | if (rc == windows.ws2_32.SOCKET_ERROR) { |
| 3083 | 3095 | switch (windows.ws2_32.WSAGetLastError()) { |
| 3084 | 3096 | .WSANOTINITIALISED => unreachable, |
| ... | ... | @@ -3091,6 +3103,7 @@ pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock |
| 3091 | 3103 | } |
| 3092 | 3104 | return; |
| 3093 | 3105 | } else { |
| 3106 | const rc = system.getsockname(sock, addr, addrlen); | |
| 3094 | 3107 | switch (errno(rc)) { |
| 3095 | 3108 | 0 => return, |
| 3096 | 3109 | else => |err| return unexpectedErrno(err), |
| ... | ... | @@ -5378,22 +5391,41 @@ pub const SetSockOptError = error{ |
| 5378 | 5391 | |
| 5379 | 5392 | /// Insufficient resources are available in the system to complete the call. |
| 5380 | 5393 | SystemResources, |
| 5394 | ||
| 5395 | NetworkSubsystemFailed, | |
| 5396 | FileDescriptorNotASocket, | |
| 5397 | SocketNotBound, | |
| 5381 | 5398 | } || UnexpectedError; |
| 5382 | 5399 | |
| 5383 | 5400 | /// Set a socket's options. |
| 5384 | pub fn setsockopt(fd: fd_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void { | |
| 5385 | switch (errno(system.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) { | |
| 5386 | 0 => {}, | |
| 5387 | EBADF => unreachable, // always a race condition | |
| 5388 | ENOTSOCK => unreachable, // always a race condition | |
| 5389 | EINVAL => unreachable, | |
| 5390 | EFAULT => unreachable, | |
| 5391 | EDOM => return error.TimeoutTooBig, | |
| 5392 | EISCONN => return error.AlreadyConnected, | |
| 5393 | ENOPROTOOPT => return error.InvalidProtocolOption, | |
| 5394 | ENOMEM => return error.SystemResources, | |
| 5395 | ENOBUFS => return error.SystemResources, | |
| 5396 | else => |err| return unexpectedErrno(err), | |
| 5401 | pub fn setsockopt(fd: socket_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void { | |
| 5402 | if (builtin.os.tag == .windows) { | |
| 5403 | const rc = windows.ws2_32.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)); | |
| 5404 | if (rc == windows.ws2_32.SOCKET_ERROR) { | |
| 5405 | switch (windows.ws2_32.WSAGetLastError()) { | |
| 5406 | .WSANOTINITIALISED => unreachable, | |
| 5407 | .WSAENETDOWN => return error.NetworkSubsystemFailed, | |
| 5408 | .WSAEFAULT => unreachable, | |
| 5409 | .WSAENOTSOCK => return error.FileDescriptorNotASocket, | |
| 5410 | .WSAEINVAL => return error.SocketNotBound, | |
| 5411 | else => |err| return windows.unexpectedWSAError(err), | |
| 5412 | } | |
| 5413 | } | |
| 5414 | return; | |
| 5415 | } else { | |
| 5416 | switch (errno(system.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len)))) { | |
| 5417 | 0 => {}, | |
| 5418 | EBADF => unreachable, // always a race condition | |
| 5419 | ENOTSOCK => unreachable, // always a race condition | |
| 5420 | EINVAL => unreachable, | |
| 5421 | EFAULT => unreachable, | |
| 5422 | EDOM => return error.TimeoutTooBig, | |
| 5423 | EISCONN => return error.AlreadyConnected, | |
| 5424 | ENOPROTOOPT => return error.InvalidProtocolOption, | |
| 5425 | ENOMEM => return error.SystemResources, | |
| 5426 | ENOBUFS => return error.SystemResources, | |
| 5427 | else => |err| return unexpectedErrno(err), | |
| 5428 | } | |
| 5397 | 5429 | } |
| 5398 | 5430 | } |
| 5399 | 5431 |
lib/std/os/bits/windows.zig+35| ... | ... | @@ -256,6 +256,41 @@ pub const POLLERR = ws2_32.POLLERR; |
| 256 | 256 | pub const POLLHUP = ws2_32.POLLHUP; |
| 257 | 257 | pub const POLLNVAL = ws2_32.POLLNVAL; |
| 258 | 258 | |
| 259 | pub const SOL_SOCKET = ws2_32.SOL_SOCKET; | |
| 260 | ||
| 261 | pub const SO_DEBUG = ws2_32.SO_DEBUG; | |
| 262 | pub const SO_ACCEPTCONN = ws2_32.SO_ACCEPTCONN; | |
| 263 | pub const SO_REUSEADDR = ws2_32.SO_REUSEADDR; | |
| 264 | pub const SO_KEEPALIVE = ws2_32.SO_KEEPALIVE; | |
| 265 | pub const SO_DONTROUTE = ws2_32.SO_DONTROUTE; | |
| 266 | pub const SO_BROADCAST = ws2_32.SO_BROADCAST; | |
| 267 | pub const SO_USELOOPBACK = ws2_32.SO_USELOOPBACK; | |
| 268 | pub const SO_LINGER = ws2_32.SO_LINGER; | |
| 269 | pub const SO_OOBINLINE = ws2_32.SO_OOBINLINE; | |
| 270 | ||
| 271 | pub const SO_DONTLINGER = ws2_32.SO_DONTLINGER; | |
| 272 | pub const SO_EXCLUSIVEADDRUSE = ws2_32.SO_EXCLUSIVEADDRUSE; | |
| 273 | ||
| 274 | pub const SO_SNDBUF = ws2_32.SO_SNDBUF; | |
| 275 | pub const SO_RCVBUF = ws2_32.SO_RCVBUF; | |
| 276 | pub const SO_SNDLOWAT = ws2_32.SO_SNDLOWAT; | |
| 277 | pub const SO_RCVLOWAT = ws2_32.SO_RCVLOWAT; | |
| 278 | pub const SO_SNDTIMEO = ws2_32.SO_SNDTIMEO; | |
| 279 | pub const SO_RCVTIMEO = ws2_32.SO_RCVTIMEO; | |
| 280 | pub const SO_ERROR = ws2_32.SO_ERROR; | |
| 281 | pub const SO_TYPE = ws2_32.SO_TYPE; | |
| 282 | ||
| 283 | pub const SO_GROUP_ID = ws2_32.SO_GROUP_ID; | |
| 284 | pub const SO_GROUP_PRIORITY = ws2_32.SO_GROUP_PRIORITY; | |
| 285 | pub const SO_MAX_MSG_SIZE = ws2_32.SO_MAX_MSG_SIZE; | |
| 286 | pub const SO_PROTOCOL_INFOA = ws2_32.SO_PROTOCOL_INFOA; | |
| 287 | pub const SO_PROTOCOL_INFOW = ws2_32.SO_PROTOCOL_INFOW; | |
| 288 | ||
| 289 | pub const PVD_CONFIG = ws2_32.PVD_CONFIG; | |
| 290 | pub const SO_CONDITIONAL_ACCEPT = ws2_32.SO_CONDITIONAL_ACCEPT; | |
| 291 | ||
| 292 | pub const TCP_NODELAY = ws2_32.TCP_NODELAY; | |
| 293 | ||
| 259 | 294 | pub const O_RDONLY = 0o0; |
| 260 | 295 | pub const O_WRONLY = 0o1; |
| 261 | 296 | pub const O_RDWR = 0o2; |
lib/std/os/linux.zig+3-3| ... | ... | @@ -1003,14 +1003,14 @@ pub fn socketpair(domain: i32, socket_type: i32, protocol: i32, fd: [2]i32) usiz |
| 1003 | 1003 | return syscall4(.socketpair, @intCast(usize, domain), @intCast(usize, socket_type), @intCast(usize, protocol), @ptrToInt(&fd[0])); |
| 1004 | 1004 | } |
| 1005 | 1005 | |
| 1006 | pub fn accept(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t) usize { | |
| 1006 | pub fn accept(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t) usize { | |
| 1007 | 1007 | if (builtin.arch == .i386) { |
| 1008 | 1008 | return socketcall(SC_accept, &[4]usize{ fd, addr, len, 0 }); |
| 1009 | 1009 | } |
| 1010 | 1010 | return accept4(fd, addr, len, 0); |
| 1011 | 1011 | } |
| 1012 | 1012 | |
| 1013 | pub fn accept4(fd: i32, noalias addr: *sockaddr, noalias len: *socklen_t, flags: u32) usize { | |
| 1013 | pub fn accept4(fd: i32, noalias addr: ?*sockaddr, noalias len: ?*socklen_t, flags: u32) usize { | |
| 1014 | 1014 | if (builtin.arch == .i386) { |
| 1015 | 1015 | return socketcall(SC_accept4, &[4]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), @ptrToInt(len), flags }); |
| 1016 | 1016 | } |
| ... | ... | @@ -1279,7 +1279,7 @@ pub fn prlimit(pid: pid_t, resource: rlimit_resource, new_limit: ?*const rlimit, |
| 1279 | 1279 | @bitCast(usize, @as(isize, pid)), |
| 1280 | 1280 | @bitCast(usize, @as(isize, @enumToInt(resource))), |
| 1281 | 1281 | @ptrToInt(new_limit), |
| 1282 | @ptrToInt(old_limit) | |
| 1282 | @ptrToInt(old_limit), | |
| 1283 | 1283 | ); |
| 1284 | 1284 | } |
| 1285 | 1285 |
lib/std/os/test.zig+1-1| ... | ... | @@ -594,7 +594,7 @@ test "fsync" { |
| 594 | 594 | |
| 595 | 595 | test "getrlimit and setrlimit" { |
| 596 | 596 | // TODO enable for other systems when implemented |
| 597 | if(builtin.os.tag != .linux){ | |
| 597 | if (builtin.os.tag != .linux) { | |
| 598 | 598 | return error.SkipZigTest; |
| 599 | 599 | } |
| 600 | 600 |
lib/std/os/windows/ws2_32.zig+42| ... | ... | @@ -718,6 +718,41 @@ const IOC_WS2 = 0x08000000; |
| 718 | 718 | |
| 719 | 719 | pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34; |
| 720 | 720 | |
| 721 | pub const SOL_SOCKET = 0xffff; | |
| 722 | ||
| 723 | pub const SO_DEBUG = 0x0001; | |
| 724 | pub const SO_ACCEPTCONN = 0x0002; | |
| 725 | pub const SO_REUSEADDR = 0x0004; | |
| 726 | pub const SO_KEEPALIVE = 0x0008; | |
| 727 | pub const SO_DONTROUTE = 0x0010; | |
| 728 | pub const SO_BROADCAST = 0x0020; | |
| 729 | pub const SO_USELOOPBACK = 0x0040; | |
| 730 | pub const SO_LINGER = 0x0080; | |
| 731 | pub const SO_OOBINLINE = 0x0100; | |
| 732 | ||
| 733 | pub const SO_DONTLINGER = ~@as(u32, SO_LINGER); | |
| 734 | pub const SO_EXCLUSIVEADDRUSE = ~@as(u32, SO_REUSEADDR); | |
| 735 | ||
| 736 | pub const SO_SNDBUF = 0x1001; | |
| 737 | pub const SO_RCVBUF = 0x1002; | |
| 738 | pub const SO_SNDLOWAT = 0x1003; | |
| 739 | pub const SO_RCVLOWAT = 0x1004; | |
| 740 | pub const SO_SNDTIMEO = 0x1005; | |
| 741 | pub const SO_RCVTIMEO = 0x1006; | |
| 742 | pub const SO_ERROR = 0x1007; | |
| 743 | pub const SO_TYPE = 0x1008; | |
| 744 | ||
| 745 | pub const SO_GROUP_ID = 0x2001; | |
| 746 | pub const SO_GROUP_PRIORITY = 0x2002; | |
| 747 | pub const SO_MAX_MSG_SIZE = 0x2003; | |
| 748 | pub const SO_PROTOCOL_INFOA = 0x2004; | |
| 749 | pub const SO_PROTOCOL_INFOW = 0x2005; | |
| 750 | ||
| 751 | pub const PVD_CONFIG = 0x3001; | |
| 752 | pub const SO_CONDITIONAL_ACCEPT = 0x3002; | |
| 753 | ||
| 754 | pub const TCP_NODELAY = 0x0001; | |
| 755 | ||
| 721 | 756 | pub extern "ws2_32" fn WSAStartup( |
| 722 | 757 | wVersionRequired: WORD, |
| 723 | 758 | lpWSAData: *WSADATA, |
| ... | ... | @@ -835,3 +870,10 @@ pub extern "ws2_32" fn getsockname( |
| 835 | 870 | name: *sockaddr, |
| 836 | 871 | namelen: *c_int, |
| 837 | 872 | ) callconv(.Stdcall) c_int; |
| 873 | pub extern "ws2_32" fn setsockopt( | |
| 874 | s: SOCKET, | |
| 875 | level: u32, | |
| 876 | optname: u32, | |
| 877 | optval: ?*const c_void, | |
| 878 | optlen: socklen_t, | |
| 879 | ) callconv(.Stdcall) c_int; |