Skip to content

Commit 1bcf85d

Browse files
normanmaurerLukasa
authored andcommitted
Correctly fail EventLoopFuture for unsupported operations on ServerSocketChannel (#226)
Motivation: ServerSocketChannel should just fail the EventLoopFuture for unsupported operations and not crash. Modifications: - Correctly fail the EventLoopFuture for unsupported operations - Add unit test. Result: No more crashes when users invoke unsupported operations.
1 parent eb60e89 commit 1bcf85d

File tree

3 files changed

+57
-0
lines changed

3 files changed

+57
-0
lines changed

Sources/NIO/SocketChannel.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,18 @@ final class ServerSocketChannel: BaseSocketChannel<ServerSocket> {
436436
ch.close(promise: nil)
437437
}
438438
}
439+
440+
override func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise<Void>?) {
441+
promise?.fail(error: ChannelError.operationUnsupported)
442+
}
443+
444+
override func markFlushPoint(promise: EventLoopPromise<Void>?) {
445+
promise?.fail(error: ChannelError.operationUnsupported)
446+
}
447+
448+
override func flushNow() -> IONotificationState {
449+
return IONotificationState.unregister
450+
}
439451
}
440452

441453
/// A channel used with datagram sockets.

Tests/NIOTests/SocketChannelTest+XCTest.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ extension SocketChannelTest {
3636
("testAcceptFailsWithEFAULT", testAcceptFailsWithEFAULT),
3737
("testSetGetOptionClosedServerSocketChannel", testSetGetOptionClosedServerSocketChannel),
3838
("testConnect", testConnect),
39+
("testWriteServerSocketChannel", testWriteServerSocketChannel),
40+
("testWriteAndFlushServerSocketChannel", testWriteAndFlushServerSocketChannel),
41+
("testConnectServerSocketChannel", testConnectServerSocketChannel),
3942
]
4043
}
4144
}

Tests/NIOTests/SocketChannelTest.swift

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,46 @@ public class SocketChannelTest : XCTestCase {
219219
try channel.closeFuture.wait()
220220
try promise.futureResult.wait()
221221
}
222+
223+
public func testWriteServerSocketChannel() throws {
224+
let group = MultiThreadedEventLoopGroup(numThreads: 1)
225+
defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }
226+
227+
let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait()
228+
do {
229+
try serverChannel.write("test").wait()
230+
} catch let err as ChannelError where err == .operationUnsupported {
231+
// expected
232+
}
233+
try serverChannel.close().wait()
234+
}
235+
236+
237+
public func testWriteAndFlushServerSocketChannel() throws {
238+
let group = MultiThreadedEventLoopGroup(numThreads: 1)
239+
defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }
240+
241+
let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait()
242+
do {
243+
try serverChannel.writeAndFlush("test").wait()
244+
} catch let err as ChannelError where err == .operationUnsupported {
245+
// expected
246+
}
247+
try serverChannel.close().wait()
248+
}
249+
250+
251+
public func testConnectServerSocketChannel() throws {
252+
let group = MultiThreadedEventLoopGroup(numThreads: 1)
253+
defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) }
254+
255+
let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait()
256+
do {
257+
try serverChannel.connect(to: serverChannel.localAddress!).wait()
258+
} catch let err as ChannelError where err == .operationUnsupported {
259+
// expected
260+
}
261+
try serverChannel.close().wait()
262+
}
263+
222264
}

0 commit comments

Comments
 (0)