From 1bcf85dd243cd51c5e9c1e164748c804af88e657 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Fri, 23 Mar 2018 16:02:31 +0100 Subject: [PATCH] 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. --- Sources/NIO/SocketChannel.swift | 12 ++++++ Tests/NIOTests/SocketChannelTest+XCTest.swift | 3 ++ Tests/NIOTests/SocketChannelTest.swift | 42 +++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/Sources/NIO/SocketChannel.swift b/Sources/NIO/SocketChannel.swift index 1c02032425..be1a636091 100644 --- a/Sources/NIO/SocketChannel.swift +++ b/Sources/NIO/SocketChannel.swift @@ -436,6 +436,18 @@ final class ServerSocketChannel: BaseSocketChannel { ch.close(promise: nil) } } + + override func bufferPendingWrite(data: NIOAny, promise: EventLoopPromise?) { + promise?.fail(error: ChannelError.operationUnsupported) + } + + override func markFlushPoint(promise: EventLoopPromise?) { + promise?.fail(error: ChannelError.operationUnsupported) + } + + override func flushNow() -> IONotificationState { + return IONotificationState.unregister + } } /// A channel used with datagram sockets. diff --git a/Tests/NIOTests/SocketChannelTest+XCTest.swift b/Tests/NIOTests/SocketChannelTest+XCTest.swift index 3427570b4c..41202c82a1 100644 --- a/Tests/NIOTests/SocketChannelTest+XCTest.swift +++ b/Tests/NIOTests/SocketChannelTest+XCTest.swift @@ -36,6 +36,9 @@ extension SocketChannelTest { ("testAcceptFailsWithEFAULT", testAcceptFailsWithEFAULT), ("testSetGetOptionClosedServerSocketChannel", testSetGetOptionClosedServerSocketChannel), ("testConnect", testConnect), + ("testWriteServerSocketChannel", testWriteServerSocketChannel), + ("testWriteAndFlushServerSocketChannel", testWriteAndFlushServerSocketChannel), + ("testConnectServerSocketChannel", testConnectServerSocketChannel), ] } } diff --git a/Tests/NIOTests/SocketChannelTest.swift b/Tests/NIOTests/SocketChannelTest.swift index 42c8a2e569..3841a5ef8f 100644 --- a/Tests/NIOTests/SocketChannelTest.swift +++ b/Tests/NIOTests/SocketChannelTest.swift @@ -219,4 +219,46 @@ public class SocketChannelTest : XCTestCase { try channel.closeFuture.wait() try promise.futureResult.wait() } + + public func testWriteServerSocketChannel() throws { + let group = MultiThreadedEventLoopGroup(numThreads: 1) + defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) } + + let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait() + do { + try serverChannel.write("test").wait() + } catch let err as ChannelError where err == .operationUnsupported { + // expected + } + try serverChannel.close().wait() + } + + + public func testWriteAndFlushServerSocketChannel() throws { + let group = MultiThreadedEventLoopGroup(numThreads: 1) + defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) } + + let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait() + do { + try serverChannel.writeAndFlush("test").wait() + } catch let err as ChannelError where err == .operationUnsupported { + // expected + } + try serverChannel.close().wait() + } + + + public func testConnectServerSocketChannel() throws { + let group = MultiThreadedEventLoopGroup(numThreads: 1) + defer { XCTAssertNoThrow(try group.syncShutdownGracefully()) } + + let serverChannel = try ServerBootstrap(group: group).bind(host: "127.0.0.1", port: 0).wait() + do { + try serverChannel.connect(to: serverChannel.localAddress!).wait() + } catch let err as ChannelError where err == .operationUnsupported { + // expected + } + try serverChannel.close().wait() + } + }