Correctly update cached addresses for accepted Channels. (#98)

Motivation:

We missed to correctly update the cached remote and local addresses for accepted Channels. Because of this localAddress and remoteAddr always returned nil.

Modifications:

- Update cached addresses when constructing SocketChannel from existing Socket.
- Add testcase

Result:

Fixes [#97].
This commit is contained in:
Norman Maurer 2018-03-05 01:44:14 -08:00 committed by Cory Benfield
parent 2c1d993978
commit f3d3267977
3 changed files with 34 additions and 0 deletions

View File

@ -206,6 +206,9 @@ class BaseSocketChannel<T: BaseSocket>: SelectableChannel, ChannelCore {
self.active.store(false)
self.recvAllocator = recvAllocator
self._pipeline = ChannelPipeline(channel: self)
// As the socket may already be connected we should ensure we start with the correct addresses cached.
self.localAddressCached.store(Box(try? socket.localAddress()))
self.remoteAddressCached.store(Box(try? socket.remoteAddress()))
}
deinit {

View File

@ -55,6 +55,7 @@ extension ChannelTests {
("testRejectsInvalidData", testRejectsInvalidData),
("testWeDontCrashIfChannelReleasesBeforePipeline", testWeDontCrashIfChannelReleasesBeforePipeline),
("testAskForLocalAndRemoteAddressesAfterChannelIsClosed", testAskForLocalAndRemoteAddressesAfterChannelIsClosed),
("testReceiveAddressAfterAccept", testReceiveAddressAfterAccept),
]
}
}

View File

@ -1412,4 +1412,34 @@ public class ChannelTests: XCTestCase {
XCTAssertNil(f)
}
}
func testReceiveAddressAfterAccept() throws {
let group = MultiThreadedEventLoopGroup(numThreads: 1)
defer {
XCTAssertNoThrow(try group.syncShutdownGracefully())
}
class AddressVerificationHandler : ChannelInboundHandler {
typealias InboundIn = Never
public func channelActive(ctx: ChannelHandlerContext) {
XCTAssertNotNil(ctx.channel.localAddress)
XCTAssertNotNil(ctx.channel.remoteAddress)
ctx.channel.close(promise: nil)
}
}
let serverChannel = try ServerBootstrap(group: group)
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEADDR), value: 1)
.childChannelInitializer { ch in
ch.pipeline.add(handler: AddressVerificationHandler())
}
.bind(host: "127.0.0.1", port: 0).wait()
let clientChannel = try ClientBootstrap(group: group)
.connect(to: serverChannel.localAddress!).wait()
try clientChannel.closeFuture.wait()
try serverChannel.syncCloseAcceptingAlreadyClosed()
}
}