Skip to content

Commit 525ff2e

Browse files
committed
WIP: shutdown
1 parent 0578678 commit 525ff2e

File tree

5 files changed

+65
-0
lines changed

5 files changed

+65
-0
lines changed

Sources/System/Internals/Constants.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -514,3 +514,13 @@ internal var _MSG_PEEK: CInt { MSG_PEEK }
514514

515515
@_alwaysEmitIntoClient
516516
internal var _MSG_WAITALL: CInt { MSG_WAITALL }
517+
518+
@_alwaysEmitIntoClient
519+
internal var _SHUT_RD: CInt { SHUT_RD }
520+
521+
@_alwaysEmitIntoClient
522+
internal var _SHUT_WR: CInt { SHUT_WR }
523+
524+
@_alwaysEmitIntoClient
525+
internal var _SHUT_RDWR: CInt { SHUT_RDWR }
526+

Sources/System/Internals/Syscalls.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,3 +122,10 @@ internal func system_socket(_ domain: CInt, type: CInt, protocol: CInt) -> CInt
122122
#endif
123123
return socket(domain, type, `protocol`)
124124
}
125+
126+
internal func system_shutdown(_ socket: CInt, _ how: CInt) -> CInt {
127+
#if ENABLE_MOCKING
128+
if mockingEnabled { return _mock(socket, how) }
129+
#endif
130+
return shutdown(socket, how)
131+
}

Sources/System/Sockets/SocketDescriptor.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,29 @@ extension SocketDescriptor {
184184
// TODO: MSG_NOSIGNAL
185185
}
186186

187+
public struct ShutdownKind: RawRepresentable, Hashable, Codable {
188+
@_alwaysEmitIntoClient
189+
public var rawValue: CInt
190+
191+
@_alwaysEmitIntoClient
192+
public init(rawValue: CInt) { self.rawValue = rawValue }
193+
194+
/// Further receives will be disallowed
195+
///
196+
/// The corresponding C constant is `SHUT_RD`
197+
public static var read: ShutdownKind { ShutdownKind(rawValue: _SHUT_RD) }
198+
199+
/// Further sends will be disallowed
200+
///
201+
/// The corresponding C constant is `SHUT_RD`
202+
public static var write: ShutdownKind { ShutdownKind(rawValue: _SHUT_WR) }
203+
204+
/// Further sends and receives will be disallowed
205+
///
206+
/// The corresponding C constant is `SHUT_RDWR`
207+
public static var readWrite: ShutdownKind { ShutdownKind(rawValue: _SHUT_RDWR) }
208+
}
209+
187210
}
188211

189212
extension SocketDescriptor {

Sources/System/Sockets/SocketOperations.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,23 @@ extension SocketDescriptor {
4848
}.map(SocketDescriptor.init(rawValue:))
4949
}
5050

51+
/// Deletes a socket's file descriptor.
52+
///
53+
/// This is equivalent to `socket.fileDescriptor.close()`
54+
@_alwaysEmitIntoClient
55+
public func close() throws { try fileDescriptor.close() }
56+
57+
/// Shutdown part of a full-duplex connection
58+
///
59+
/// The corresponding C function is `shutdown`
60+
@_alwaysEmitIntoClient
61+
public func shutdown(_ how: ShutdownKind) throws {
62+
try _shutdown(how).get()
63+
}
64+
65+
@usableFromInline
66+
internal func _shutdown(_ how: ShutdownKind) -> Result<(), Errno> {
67+
nothingOrErrno(system_shutdown(self.rawValue, how.rawValue))
68+
}
5169

5270
}

Tests/SystemTests/SocketTest.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@ final class SocketTest: XCTestCase {
2020

2121
func testSyscalls() {
2222

23+
let socket = SocketDescriptor(rawValue: 3)
24+
let rawSocket = socket.rawValue
25+
2326
let syscallTestCases: Array<MockTestCase> = [
2427
MockTestCase(name: "socket", PF_INET6, SOCK_STREAM, 0, interruptable: true) {
2528
retryOnInterrupt in
2629
_ = try SocketDescriptor.open(.ipv6, .stream, retryOnInterrupt: retryOnInterrupt)
2730
},
31+
MockTestCase(name: "shutdown", rawSocket, SHUT_RD, interruptable: false) {
32+
retryOnInterrupt in
33+
_ = try socket.shutdown(.read)
34+
},
2835
]
2936

3037
syscallTestCases.forEach { $0.runAllTests() }

0 commit comments

Comments
 (0)