LineBasedFrameDecoder: Don't discard everything after EOF (#39)

Motivation:

LineBasedFrameDecoder discarded everything after EOF and delivered it in
the left-over bytes error. For the real world however that doesn't make
much sense, you'd want all previously received lines and only receive
the partial lines as left-overs.

Modifications:

deliver lines until there are only partial lines left, even in case of
EOF.

Result:

LineBasedFrameDecoder more useful
This commit is contained in:
Johannes Weiss 2019-03-21 14:55:21 +00:00 committed by GitHub
parent 66c13a41c7
commit 1c39f44412
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 3 deletions

View File

@ -49,6 +49,7 @@ public class LineBasedFrameDecoder: ByteToMessageDecoder {
} }
public func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState { public func decodeLast(context: ChannelHandlerContext, buffer: inout ByteBuffer, seenEOF: Bool) throws -> DecodingState {
while try self.decode(context: context, buffer: &buffer) == .continue {}
if buffer.readableBytes > 0 { if buffer.readableBytes > 0 {
context.fireErrorCaught(NIOExtrasErrors.LeftOverBytesError(leftOverBytes: buffer)) context.fireErrorCaught(NIOExtrasErrors.LeftOverBytesError(leftOverBytes: buffer))
} }

View File

@ -25,7 +25,7 @@ class LineBasedFrameDecoderTest: XCTestCase {
self.channel = EmbeddedChannel() self.channel = EmbeddedChannel()
self.decoder = LineBasedFrameDecoder() self.decoder = LineBasedFrameDecoder()
self.handler = ByteToMessageHandler(self.decoder) self.handler = ByteToMessageHandler(self.decoder)
try? self.channel.pipeline.addHandler(self.handler).wait() XCTAssertNoThrow(try self.channel.pipeline.addHandler(self.handler).wait())
} }
override func tearDown() { override func tearDown() {
@ -141,6 +141,7 @@ class LineBasedFrameDecoderTest: XCTestCase {
func channelRead(context: ChannelHandlerContext, data: NIOAny) { func channelRead(context: ChannelHandlerContext, data: NIOAny) {
let buffer = self.unwrapInboundIn(data) let buffer = self.unwrapInboundIn(data)
context.fireChannelRead(data)
if buffer.readableBytes == 3 { if buffer.readableBytes == 3 {
context.close(promise: nil) context.close(promise: nil)
@ -159,9 +160,16 @@ class LineBasedFrameDecoderTest: XCTestCase {
let handler = CloseWhenMyFavouriteMessageArrives(receivedLeftOversPromise: receivedLeftOversPromise) let handler = CloseWhenMyFavouriteMessageArrives(receivedLeftOversPromise: receivedLeftOversPromise)
XCTAssertNoThrow(try self.channel.pipeline.addHandler(handler).wait()) XCTAssertNoThrow(try self.channel.pipeline.addHandler(handler).wait())
var buffer = self.channel.allocator.buffer(capacity: 16) var buffer = self.channel.allocator.buffer(capacity: 16)
buffer.writeString("a\nbb\nccc\ndddd\neeeee\nffffff\n") buffer.writeString("a\nbb\nccc\ndddd\neeeee\nffffff\nXXX")
XCTAssertNoThrow(try self.channel.writeInbound(buffer)) XCTAssertNoThrow(try self.channel.writeInbound(buffer))
XCTAssertNoThrow(try XCTAssertEqual("dddd\neeeee\nffffff\n", for s in ["a", "bb", "ccc", "dddd", "eeeee", "ffffff"] {
XCTAssertNoThrow(XCTAssertEqual(s,
(try self.channel.readInbound(as: ByteBuffer.self)?.readableBytesView).map {
String(decoding: $0, as: Unicode.UTF8.self)
}))
}
XCTAssertNoThrow(XCTAssertNil(try self.channel.readInbound(as: ByteBuffer.self)))
XCTAssertNoThrow(try XCTAssertEqual("XXX",
String(decoding: receivedLeftOversPromise.futureResult.wait().readableBytesView, String(decoding: receivedLeftOversPromise.futureResult.wait().readableBytesView,
as: UTF8.self))) as: UTF8.self)))
} }