Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/std/c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ pub extern "c" fn ioctl(fd: fd_t, request: c_int, ...) c_int;
pub extern "c" fn uname(buf: *utsname) c_int;

pub extern "c" fn gethostname(name: [*]u8, len: usize) c_int;
pub extern "c" fn shutdown(socket: fd_t, how: c_int) c_int;
pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: socklen_t) c_int;
pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
Expand Down
56 changes: 56 additions & 0 deletions lib/std/os.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,62 @@ pub fn socket(domain: u32, socket_type: u32, protocol: u32) SocketError!socket_t
}
}

pub const ShutdownError = error{
ConnectionAborted,

/// Connection was reset by peer, application should close socket as it is no longer usable.
ConnectionResetByPeer,

BlockingOperationInProgress,

/// The network subsystem has failed.
NetworkSubsystemFailed,

/// The socket is not connected (connection-oriented sockets only).
SocketNotConnected,

SystemResources
} || UnexpectedError;

pub const ShutdownHow = enum { recv, send, both };

/// Shutdown socket send/receive operations
pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void {
if (builtin.os.tag == .windows) {
const result = windows.ws2_32.shutdown(sock, switch (how) {
.recv => windows.SD_RECEIVE,
.send => windows.SD_SEND,
.both => windows.SD_BOTH,
});
if (0 != result) switch (windows.ws2_32.WSAGetLastError()) {
.WSAECONNABORTED => return error.ConnectionAborted,
.WSAECONNRESET => return error.ConnectionResetByPeer,
.WSAEINPROGRESS => return error.BlockingOperationInProgress,
.WSAEINVAL => unreachable,
.WSAENETDOWN => return error.NetworkSubsystemFailed,
.WSAENOTCONN => return error.SocketNotConnected,
.WSAENOTSOCK => unreachable,
.WSANOTINITIALISED => unreachable,
else => |err| return windows.unexpectedWSAError(err),
};
} else {
const rc = system.shutdown(sock, switch (how) {
.recv => SHUT_RD,
.send => SHUT_WR,
.both => SHUT_RDWR,
});
switch (errno(rc)) {
0 => return,
EBADF => unreachable,
EINVAL => unreachable,
ENOTCONN => return error.SocketNotConnected,
ENOTSOCK => unreachable,
ENOBUFS => return error.SystemResources,
else => |err| return unexpectedErrno(err),
}
}
}

pub fn closeSocket(sock: socket_t) void {
if (builtin.os.tag == .windows) {
windows.closesocket(sock) catch unreachable;
Expand Down
4 changes: 4 additions & 0 deletions lib/std/os/bits/darwin.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1523,3 +1523,7 @@ pub const rlimit = extern struct {
/// Hard limit
max: rlim_t,
};

pub const SHUT_RD = 0;
pub const SHUT_WR = 1;
pub const SHUT_RDWR = 2;
4 changes: 4 additions & 0 deletions lib/std/os/bits/freebsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1388,3 +1388,7 @@ pub const rlimit = extern struct {
/// Hard limit
max: rlim_t,
};

pub const SHUT_RD = 0;
pub const SHUT_WR = 1;
pub const SHUT_RDWR = 2;
4 changes: 4 additions & 0 deletions lib/std/os/bits/netbsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1196,3 +1196,7 @@ pub const rlimit = extern struct {
/// Hard limit
max: rlim_t,
};

pub const SHUT_RD = 0;
pub const SHUT_WR = 1;
pub const SHUT_RDWR = 2;
4 changes: 4 additions & 0 deletions lib/std/os/bits/openbsd.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1134,3 +1134,7 @@ pub const rlimit = extern struct {
/// Hard limit
max: rlim_t,
};

pub const SHUT_RD = 0;
pub const SHUT_WR = 1;
pub const SHUT_RDWR = 2;
19 changes: 19 additions & 0 deletions lib/std/os/test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -627,3 +627,22 @@ test "getrlimit and setrlimit" {
try os.setrlimit(resource, limit);
}
}

test "shutdown socket" {
if (builtin.os.tag == .wasi)
return error.SkipZigTest;
if (builtin.os.tag == .windows) {
_ = try std.os.windows.WSAStartup(2, 2);
}
defer {
if (builtin.os.tag == .windows) {
std.os.windows.WSACleanup() catch unreachable;
}
}
const sock = try os.socket(os.AF_INET, os.SOCK_STREAM, 0);
os.shutdown(sock, .both) catch |err| switch (err) {
error.SocketNotConnected => {},
else => |e| return e,
};
os.closeSocket(sock);
}
4 changes: 4 additions & 0 deletions lib/std/os/windows/bits.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1602,3 +1602,7 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
MountPoints: [1]MOUNTMGR_MOUNT_POINT,
};
pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;

pub const SD_RECEIVE = 0;
pub const SD_SEND = 1;
pub const SD_BOTH = 2;
4 changes: 4 additions & 0 deletions lib/std/os/windows/ws2_32.zig
Original file line number Diff line number Diff line change
Expand Up @@ -877,3 +877,7 @@ pub extern "ws2_32" fn setsockopt(
optval: ?*const c_void,
optlen: socklen_t,
) callconv(WINAPI) c_int;
pub extern "ws2_32" fn shutdown(
s: SOCKET,
how: c_int,
) callconv(WINAPI) c_int;