Strict concurrency for NIONFS3 and NIONFS3Tests (#264)

This commit is contained in:
George Barnett 2025-04-07 15:09:17 +01:00 committed by GitHub
parent 96bce550c6
commit b6b5e1133f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 39 additions and 21 deletions

View File

@ -155,7 +155,8 @@ var targets: [PackageDescription.Target] = [
name: "NIONFS3",
dependencies: [
.product(name: "NIOCore", package: "swift-nio")
]
],
swiftSettings: strictConcurrencySettings
),
.testTarget(
name: "NIONFS3Tests",
@ -164,7 +165,8 @@ var targets: [PackageDescription.Target] = [
.product(name: "NIOCore", package: "swift-nio"),
.product(name: "NIOEmbedded", package: "swift-nio"),
.product(name: "NIOTestUtils", package: "swift-nio"),
]
],
swiftSettings: strictConcurrencySettings
),
.target(
name: "NIOHTTPTypes",

View File

@ -14,7 +14,7 @@
import NIOCore
public struct NFS3CallDecoder: NIOSingleStepByteToMessageDecoder {
public struct NFS3CallDecoder: NIOSingleStepByteToMessageDecoder, Sendable {
public typealias InboundOut = RPCNFS3Call
public init() {}

View File

@ -14,7 +14,7 @@
import NIOCore
public struct NFS3CallEncoder: MessageToByteEncoder {
public struct NFS3CallEncoder: MessageToByteEncoder, Sendable {
public typealias OutboundIn = RPCNFS3Call
public init() {}

View File

@ -14,7 +14,11 @@
import NIOCore
public protocol NFS3FileSystemNoAuth {
@preconcurrency
public protocol NFS3FileSystemNoAuth: Sendable {
// Must be Sendable; there are extensions which take an event loop and call these functions
// on that event loop.
func mount(_ call: MountCallMount, promise: EventLoopPromise<MountReplyMount>)
func unmount(_ call: MountCallUnmount, promise: EventLoopPromise<MountReplyUnmount>)
func getattr(_ call: NFS3CallGetAttr, promise: EventLoopPromise<NFS3ReplyGetAttr>)

View File

@ -22,7 +22,7 @@ import NIOCore
/// `NFS3FileSystemNoAuthHandler` ignores any [SUN RPC](https://datatracker.ietf.org/doc/html/rfc5531) credentials /
/// verifiers and always replies with `AUTH_NONE`. If you need to implement access control via UNIX user/group, this
/// handler will not be enough. It assumes that every call is allowed. Please note that this is not a security risk
/// because NFS3 tranditionally just trusts the UNIX uid/gid that the client provided. So there's no security value
/// because NFS3 traditionally just trusts the UNIX uid/gid that the client provided. So there's no security value
/// added by verifying them. However, the client may rely on the server to check the UNIX permissions (whilst trusting
/// the uid/gid) which cannot be done with this handler.
public final class NFS3FileSystemNoAuthHandler<FS: NFS3FileSystemNoAuth>: ChannelDuplexHandler, NFS3FileSystemResponder
@ -118,3 +118,6 @@ public final class NFS3FileSystemNoAuthHandler<FS: NFS3FileSystemNoAuth>: Channe
context.fireErrorCaught(error)
}
}
@available(*, unavailable)
extension NFS3FileSystemNoAuthHandler: Sendable {}

View File

@ -39,7 +39,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
case .mountNull:
self.sink.sendSuccessfulReply(.mountNull, call: callMessage)
case .mount(let call):
self.fs.mount(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.mount(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.mount(reply), call: callMessage)
@ -48,7 +48,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .unmount(let call):
self.fs.unmount(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.unmount(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.unmount(reply), call: callMessage)
@ -59,7 +59,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
case .null:
self.sink.sendSuccessfulReply(.null, call: callMessage)
case .getattr(let call):
self.fs.getattr(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.getattr(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.getattr(reply), call: callMessage)
@ -68,7 +68,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .fsinfo(let call):
self.fs.fsinfo(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.fsinfo(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.fsinfo(reply), call: callMessage)
@ -77,7 +77,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .pathconf(let call):
self.fs.pathconf(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.pathconf(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.pathconf(reply), call: callMessage)
@ -86,7 +86,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .fsstat(let call):
self.fs.fsstat(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.fsstat(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.fsstat(reply), call: callMessage)
@ -95,7 +95,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .access(let call):
self.fs.access(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.access(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.access(reply), call: callMessage)
@ -104,7 +104,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .lookup(let call):
self.fs.lookup(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.lookup(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.lookup(reply), call: callMessage)
@ -113,7 +113,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .readdirplus(let call):
self.fs.readdirplus(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.readdirplus(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.readdirplus(reply), call: callMessage)
@ -122,7 +122,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .read(let call):
self.fs.read(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.read(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.read(reply), call: callMessage)
@ -131,7 +131,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .readdir(let call):
self.fs.readdir(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.readdir(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.readdir(reply), call: callMessage)
@ -140,7 +140,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .readlink(let call):
self.fs.readlink(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.readlink(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.readlink(reply), call: callMessage)
@ -149,7 +149,7 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
case .setattr(let call):
self.fs.setattr(call, eventLoop: self.eventLoop).whenComplete { result in
self.fs.setattr(call, eventLoop: self.eventLoop).assumeIsolated().whenComplete { result in
switch result {
case .success(let reply):
self.sink.sendSuccessfulReply(.setattr(reply), call: callMessage)
@ -163,3 +163,6 @@ internal struct NFS3FileSystemInvoker<FS: NFS3FileSystemNoAuth, Sink: NFS3FileSy
}
}
}
@available(*, unavailable)
extension NFS3FileSystemInvoker: Sendable {}

View File

@ -150,3 +150,6 @@ extension NFS3FileSystemServerHandler: NFS3FileSystemResponder {
}
}
}
@available(*, unavailable)
extension NFS3FileSystemServerHandler: Sendable {}

View File

@ -67,3 +67,6 @@ public struct NFS3ReplyDecoder: WriteObservingByteToMessageDecoder {
self.procedures[data.rpcCall.xid] = data.rpcCall.programAndProcedure
}
}
@available(*, unavailable)
extension NFS3ReplyDecoder: Sendable {}

View File

@ -14,7 +14,7 @@
import NIOCore
public struct NFS3ReplyEncoder: MessageToByteEncoder {
public struct NFS3ReplyEncoder: MessageToByteEncoder, Sendable {
public typealias OutboundIn = RPCNFS3Reply
public init() {}

View File

@ -19,7 +19,7 @@ import XCTest
final class NFS3FileSystemTests: XCTestCase {
func testReadDirDefaultImplementation() throws {
class MyOnlyReadDirPlusFS: NFS3FileSystemNoAuth {
final class MyOnlyReadDirPlusFS: NFS3FileSystemNoAuth {
func shutdown(promise: EventLoopPromise<Void>) {
promise.succeed(())
}