Skip to content

Commit 2bca2e4

Browse files
committed
add std.os.shutdown function for sockets
1 parent abc729a commit 2bca2e4

File tree

9 files changed

+93
-0
lines changed

9 files changed

+93
-0
lines changed

lib/std/c.zig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ pub extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;
145145
pub extern "c" fn uname(buf: *utsname) c_int;
146146

147147
pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;
148+
pub extern "c" fn shutdown(socket: fd_t, how: i32) usize;
148149
pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
149150
pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
150151
pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;

lib/std/os.zig

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2706,6 +2706,58 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
27062706
}
27072707
}
27082708

2709+
pub 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+
2726+
pub const ShutdownHow = enum {
2727+
recv = if (builtin.os.tag == .windows) windows.SD_RECEIVE else SHUT_RD,
2728+
send = if (builtin.os.tag == .windows) windows.SD_SEND else SHUT_WR,
2729+
both = if (builtin.os.tag == .windows) windows.SD_BOTH else SHUT_RDWR,
2730+
};
2731+
2732+
/// Shutdown socket send/receive operations
2733+
pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void {
2734+
if (builtin.os.tag == .windows) {
2735+
const result = windows.ws2_32.shutdown(sock, @enumToInt(how));
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, @enumToInt(how));
2749+
switch (errno(rc)) {
2750+
0 => return,
2751+
EBADF => unreachable,
2752+
EINVAL => unreachable,
2753+
ENOTCONN => return error.SocketNotConnected,
2754+
ENOTSOCK => unreachable,
2755+
ENOBUFS => return error.SystemResources,
2756+
else => |err| return unexpectedErrno(err),
2757+
}
2758+
}
2759+
}
2760+
27092761
pub fn closeSocket(sock: socket_t) void {
27102762
if (builtin.os.tag == .windows) {
27112763
windows.closesocket(sock) catch unreachable;

lib/std/os/bits/darwin.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,3 +1523,7 @@ pub const rlimit = extern struct {
15231523
/// Hard limit
15241524
max: rlim_t,
15251525
};
1526+
1527+
pub const SHUT_RD = 0;
1528+
pub const SHUT_WR = 1;
1529+
pub const SHUT_RDWR = 2;

lib/std/os/bits/freebsd.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1388,3 +1388,7 @@ pub const rlimit = extern struct {
13881388
/// Hard limit
13891389
max: rlim_t,
13901390
};
1391+
1392+
pub const SHUT_RD = 0;
1393+
pub const SHUT_WR = 1;
1394+
pub const SHUT_RDWR = 2;

lib/std/os/bits/netbsd.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,3 +1196,7 @@ pub const rlimit = extern struct {
11961196
/// Hard limit
11971197
max: rlim_t,
11981198
};
1199+
1200+
pub const SHUT_RD = 0;
1201+
pub const SHUT_WR = 1;
1202+
pub const SHUT_RDWR = 2;

lib/std/os/bits/openbsd.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,3 +1134,7 @@ pub const rlimit = extern struct {
11341134
/// Hard limit
11351135
max: rlim_t,
11361136
};
1137+
1138+
pub const SHUT_RD = 0;
1139+
pub const SHUT_WR = 1;
1140+
pub const SHUT_RDWR = 2;

lib/std/os/test.zig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,3 +627,19 @@ test "getrlimit and setrlimit" {
627627
try os.setrlimit(resource, limit);
628628
}
629629
}
630+
631+
test "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 {}; // should fail
644+
os.closeSocket(sock);
645+
}

lib/std/os/windows/bits.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1602,3 +1602,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
16021602
MountPoints: [1]MOUNTMGR_MOUNT_POINT,
16031603
};
16041604
pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;
1605+
1606+
pub const SD_RECEIVE = 0;
1607+
pub const SD_SEND = 1;
1608+
pub const SD_BOTH = 2;

lib/std/os/windows/ws2_32.zig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,3 +877,7 @@ pub extern "ws2_32" fn setsockopt(
877877
optval: ?*const c_void,
878878
optlen: socklen_t,
879879
) callconv(WINAPI) c_int;
880+
pub extern "ws2_32" fn shutdown(
881+
s: SOCKET,
882+
how: c_int,
883+
) callconv(WINAPI) c_int;

0 commit comments

Comments
 (0)