authorgravatar for johnnymarler@gmail.comJonathan Marler <johnnymarler@gmail.com> 2020-11-28 00:42:17-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-11-30 11:25:03-08:00
logb587a42233728a523c89a24caab1c68d60774fac
tree0c532dd35852e7f6ee04162564254bfec6658641
parentbaa075ac8cf3ff666b9f3d5c5a75e139f33b5d86

add std.os.shutdown function for sockets


9 files changed, 100 insertions(+), 0 deletions(-)

lib/std/c.zig+1
...@@ -145,6 +145,7 @@ pub extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;...@@ -145,6 +145,7 @@ pub extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;
145pub extern "c" fn uname(buf: *utsname) c_int;145pub extern "c" fn uname(buf: *utsname) c_int;
146146
147pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;147pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;
148pub extern "c" fn shutdown(socket: fd_t, how: c_int) c_int;
148pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;149pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
149pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;150pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
150pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;151pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
lib/std/os.zig+56
...@@ -2706,6 +2706,62 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t...@@ -2706,6 +2706,62 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
2706 }2706 }
2707}2707}
27082708
2709pub const ShutdownError = error{
2710 ConnectionAborted,
2711
2712 /// Connection was reset by peer, application should close socket as it is no longer usable.
2713 ConnectionResetByPeer,
2714
2715 BlockingOperationInProgress,
2716
2717 /// The network subsystem has failed.
2718 NetworkSubsystemFailed,
2719
2720 /// The socket is not connected (connection-oriented sockets only).
2721 SocketNotConnected,
2722
2723 SystemResources
2724} || UnexpectedError;
2725
2726pub const ShutdownHow = enum { recv, send, both };
2727
2728/// Shutdown socket send/receive operations
2729pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void {
2730 if (builtin.os.tag == .windows) {
2731 const result = windows.ws2_32.shutdown(sock, switch (how) {
2732 .recv => windows.SD_RECEIVE,
2733 .send => windows.SD_SEND,
2734 .both => windows.SD_BOTH,
2735 });
2736 if (0 != result) switch (windows.ws2_32.WSAGetLastError()) {
2737 .WSAECONNABORTED => return error.ConnectionAborted,
2738 .WSAECONNRESET => return error.ConnectionResetByPeer,
2739 .WSAEINPROGRESS => return error.BlockingOperationInProgress,
2740 .WSAEINVAL => unreachable,
2741 .WSAENETDOWN => return error.NetworkSubsystemFailed,
2742 .WSAENOTCONN => return error.SocketNotConnected,
2743 .WSAENOTSOCK => unreachable,
2744 .WSANOTINITIALISED => unreachable,
2745 else => |err| return windows.unexpectedWSAError(err),
2746 };
2747 } else {
2748 const rc = system.shutdown(sock, switch (how) {
2749 .recv => SHUT_RD,
2750 .send => SHUT_WR,
2751 .both => SHUT_RDWR,
2752 });
2753 switch (errno(rc)) {
2754 0 => return,
2755 EBADF => unreachable,
2756 EINVAL => unreachable,
2757 ENOTCONN => return error.SocketNotConnected,
2758 ENOTSOCK => unreachable,
2759 ENOBUFS => return error.SystemResources,
2760 else => |err| return unexpectedErrno(err),
2761 }
2762 }
2763}
2764
2709pub fn closeSocket(sock: socket_t) void {2765pub fn closeSocket(sock: socket_t) void {
2710 if (builtin.os.tag == .windows) {2766 if (builtin.os.tag == .windows) {
2711 windows.closesocket(sock) catch unreachable;2767 windows.closesocket(sock) catch unreachable;
lib/std/os/bits/darwin.zig+4
...@@ -1523,3 +1523,7 @@ pub const rlimit = extern struct {...@@ -1523,3 +1523,7 @@ pub const rlimit = extern struct {
1523 /// Hard limit1523 /// Hard limit
1524 max: rlim_t,1524 max: rlim_t,
1525};1525};
1526
1527pub const SHUT_RD = 0;
1528pub const SHUT_WR = 1;
1529pub const SHUT_RDWR = 2;
lib/std/os/bits/freebsd.zig+4
...@@ -1388,3 +1388,7 @@ pub const rlimit = extern struct {...@@ -1388,3 +1388,7 @@ pub const rlimit = extern struct {
1388 /// Hard limit1388 /// Hard limit
1389 max: rlim_t,1389 max: rlim_t,
1390};1390};
1391
1392pub const SHUT_RD = 0;
1393pub const SHUT_WR = 1;
1394pub const SHUT_RDWR = 2;
lib/std/os/bits/netbsd.zig+4
...@@ -1196,3 +1196,7 @@ pub const rlimit = extern struct {...@@ -1196,3 +1196,7 @@ pub const rlimit = extern struct {
1196 /// Hard limit1196 /// Hard limit
1197 max: rlim_t,1197 max: rlim_t,
1198};1198};
1199
1200pub const SHUT_RD = 0;
1201pub const SHUT_WR = 1;
1202pub const SHUT_RDWR = 2;
lib/std/os/bits/openbsd.zig+4
...@@ -1134,3 +1134,7 @@ pub const rlimit = extern struct {...@@ -1134,3 +1134,7 @@ pub const rlimit = extern struct {
1134 /// Hard limit1134 /// Hard limit
1135 max: rlim_t,1135 max: rlim_t,
1136};1136};
1137
1138pub const SHUT_RD = 0;
1139pub const SHUT_WR = 1;
1140pub const SHUT_RDWR = 2;
lib/std/os/test.zig+19
...@@ -627,3 +627,22 @@ test "getrlimit and setrlimit" {...@@ -627,3 +627,22 @@ test "getrlimit and setrlimit" {
627 try os.setrlimit(resource, limit);627 try os.setrlimit(resource, limit);
628 }628 }
629}629}
630
631test "shutdown socket" {
632 if (builtin.os.tag == .wasi)
633 return error.SkipZigTest;
634 if (builtin.os.tag == .windows) {
635 _ = try std.os.windows.WSAStartup(2, 2);
636 }
637 defer {
638 if (builtin.os.tag == .windows) {
639 std.os.windows.WSACleanup() catch unreachable;
640 }
641 }
642 const sock = try os.socket(os.AF_INET, os.SOCK_STREAM, 0);
643 os.shutdown(sock, .both) catch |err| switch (err) {
644 error.SocketNotConnected => {},
645 else => |e| return e,
646 };
647 os.closeSocket(sock);
648}
lib/std/os/windows/bits.zig+4
...@@ -1602,3 +1602,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {...@@ -1602,3 +1602,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
1602 MountPoints: [1]MOUNTMGR_MOUNT_POINT,1602 MountPoints: [1]MOUNTMGR_MOUNT_POINT,
1603};1603};
1604pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;1604pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;
1605
1606pub const SD_RECEIVE = 0;
1607pub const SD_SEND = 1;
1608pub const SD_BOTH = 2;
lib/std/os/windows/ws2_32.zig+4
...@@ -877,3 +877,7 @@ pub extern "ws2_32" fn setsockopt(...@@ -877,3 +877,7 @@ pub extern "ws2_32" fn setsockopt(
877 optval: ?*const c_void,877 optval: ?*const c_void,
878 optlen: socklen_t,878 optlen: socklen_t,
879) callconv(WINAPI) c_int;879) callconv(WINAPI) c_int;
880pub extern "ws2_32" fn shutdown(
881 s: SOCKET,
882 how: c_int,
883) callconv(WINAPI) c_int;