Skip to content

Commit a7be981

Browse files
author
Pushkar N Kulkarni
authored
Merge pull request #217 from IBM-Swift/ctx-bug
Remove a race condition from the WebSocket upgrade
2 parents ee75eeb + 09b88f8 commit a7be981

File tree

3 files changed

+16
-20
lines changed

3 files changed

+16
-20
lines changed

Sources/KituraNet/HTTP/HTTPRequestHandler.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ internal class HTTPRequestHandler: ChannelInboundHandler, RemovableChannelHandle
7979

8080
switch request {
8181
case .head(let header):
82-
serverRequest = HTTPServerRequest(ctx: context, requestHead: header, enableSSL: enableSSLVerification)
82+
serverRequest = HTTPServerRequest(channel: context.channel, requestHead: header, enableSSL: enableSSLVerification)
8383
self.clientRequestedKeepAlive = header.isKeepAlive
8484
case .body(var buffer):
8585
guard let serverRequest = serverRequest else {

Sources/KituraNet/HTTP/HTTPServer.swift

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,8 +124,6 @@ public class HTTPServer: Server {
124124
/// The event loop group on which the HTTP handler runs
125125
private let eventLoopGroup: MultiThreadedEventLoopGroup
126126

127-
private var ctx: ChannelHandlerContext?
128-
129127
/**
130128
Creates an HTTP server object.
131129

@@ -193,19 +191,18 @@ public class HTTPServer: Server {
193191
}
194192

195193
/// Creates upgrade request and adds WebSocket handler to pipeline
196-
private func upgradeHandler(webSocketHandlerFactory: ProtocolHandlerFactory, request: HTTPRequestHead) -> EventLoopFuture<Void> {
197-
guard let ctx = self.ctx else { fatalError("The channel was probably closed during a protocol upgrade.") }
198-
return ctx.eventLoop.submit {
199-
let request = HTTPServerRequest(ctx: ctx, requestHead: request, enableSSL: false)
194+
private func upgradeHandler(channel: Channel, webSocketHandlerFactory: ProtocolHandlerFactory, request: HTTPRequestHead) -> EventLoopFuture<Void> {
195+
return channel.eventLoop.submit {
196+
let request = HTTPServerRequest(channel: channel, requestHead: request, enableSSL: false)
200197
return webSocketHandlerFactory.handler(for: request)
201198
}.flatMap { (handler: ChannelHandler) -> EventLoopFuture<Void> in
202-
return ctx.channel.pipeline.addHandler(handler).flatMap {
199+
return channel.pipeline.addHandler(handler).flatMap {
203200
if let _extensions = request.headers["Sec-WebSocket-Extensions"].first {
204201
let handlers = webSocketHandlerFactory.extensionHandlers(header: _extensions)
205-
return ctx.channel.pipeline.addHandlers(handlers, position: .before(handler))
202+
return channel.pipeline.addHandlers(handlers, position: .before(handler))
206203
} else {
207204
// No extensions. We must return success.
208-
return ctx.channel.eventLoop.makeSucceededFuture(())
205+
return channel.eventLoop.makeSucceededFuture(())
209206
}
210207
}
211208
}
@@ -222,7 +219,7 @@ public class HTTPServer: Server {
222219

223220
private func generateUpgradePipelineHandler(_ webSocketHandlerFactory: ProtocolHandlerFactory) -> UpgradePipelineHandlerFunction {
224221
return { (channel: Channel, request: HTTPRequestHead) in
225-
return self.upgradeHandler(webSocketHandlerFactory: webSocketHandlerFactory, request: request)
222+
return self.upgradeHandler(channel: channel, webSocketHandlerFactory: webSocketHandlerFactory, request: request)
226223
}
227224
}
228225

@@ -304,8 +301,7 @@ public class HTTPServer: Server {
304301
.serverChannelOption(ChannelOptions.socket(SocketOptionLevel(SOL_SOCKET), SO_REUSEPORT), value: allowPortReuse ? 1 : 0)
305302
.childChannelInitializer { channel in
306303
let httpHandler = HTTPRequestHandler(for: self)
307-
let config: NIOHTTPServerUpgradeConfiguration = (upgraders: upgraders, completionHandler: { ctx in
308-
self.ctx = ctx
304+
let config: NIOHTTPServerUpgradeConfiguration = (upgraders: upgraders, completionHandler: { _ in
309305
_ = channel.pipeline.removeHandler(httpHandler)
310306
})
311307
return channel.pipeline.configureHTTPServerPipeline(withServerUpgrade: config, withErrorHandling: true).flatMap {

Sources/KituraNet/HTTP/HTTPServerRequest.swift

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public class HTTPServerRequest: ServerRequest {
180180
*/
181181
public var method: String
182182

183-
private let ctx: ChannelHandlerContext
183+
private let channel: Channel
184184

185185
private var enableSSL: Bool = false
186186

@@ -208,20 +208,20 @@ public class HTTPServerRequest: ServerRequest {
208208
}
209209
}
210210

211-
init(ctx: ChannelHandlerContext, requestHead: HTTPRequestHead, enableSSL: Bool) {
211+
init(channel: Channel, requestHead: HTTPRequestHead, enableSSL: Bool) {
212212
// An HTTPServerRequest may be created only on the EventLoop assigned to handle
213213
// the connection on which the HTTP request arrived.
214-
assert(ctx.eventLoop.inEventLoop)
215-
self.ctx = ctx
214+
assert(channel.eventLoop.inEventLoop)
215+
self.channel = channel
216216
self.headers = HeadersContainer(with: requestHead.headers)
217217
self.method = requestHead.method.rawValue
218218
self.httpVersionMajor = UInt16(requestHead.version.major)
219219
self.httpVersionMinor = UInt16(requestHead.version.minor)
220220
self.rawURLString = requestHead.uri
221221
self.enableSSL = enableSSL
222-
self.localAddressHost = HTTPServerRequest.host(socketAddress: ctx.localAddress)
223-
self.localAddressPort = ctx.localAddress?.port ?? 0
224-
self.remoteAddress = HTTPServerRequest.host(socketAddress: ctx.remoteAddress)
222+
self.localAddressHost = HTTPServerRequest.host(socketAddress: channel.localAddress)
223+
self.localAddressPort = channel.localAddress?.port ?? 0
224+
self.remoteAddress = HTTPServerRequest.host(socketAddress: channel.remoteAddress)
225225
}
226226

227227
var buffer: BufferList?

0 commit comments

Comments
 (0)