I'm not being very successful with hacking out a solution.
If someone can explain something to me, or point out serious flaws (other than not handling errors), that would probably help me get further.
The above code works fine until a large file needs to be de-chunked.
Tracing things out with prints, I find this when adding a decoder -
I can de-chunk, but I need to use nc -q1 ... when testing,
and it throws an exception when going to write. Large or small file sent.
In the tracing I can see things are de-chunked when needed, and a proper information goes to and comes from the "business logic", and the exception is being thrown at try await connectionChannelOutbound.write
. The exception is The operation could not be completed. (NIOCore.NIOAsyncWriterError error 1.)
.
(I'm not worried about the needing -q1 when testing with nc at a BASH prompt, guessing not a problem with a real world client, or that is easily done.)
try childChannel.pipeline.syncOperations.addHandler(ByteToMessageHandler(RequestDecoder7()))
return try NIOAsyncChannel<ByteBuffer, ByteBuffer>(wrappingChannelSynchronously: childChannel)
for try await inboundData in connectionChannelInbound {
print("Service start: inboundData in connectionChannelInbound top of loop, readableBytes is \(inboundData.readableBytes)")
let response2Send = await ServerChore (requestToHandle: String (buffer: inboundData))
print("Service start: after ServerChore output is \(response2Send)")
try await connectionChannelOutbound.write (NIOCore.ByteBuffer (string: response2Send))
I had tried this earlier with passing strings around as well, same results.
struct RequestDecoder7: NIOSingleStepByteToMessageDecoder {
typealias InboundOut = NIOCore.ByteBuffer
var fileSize: UInt64?
mutating func decode(buffer: inout NIOCore.ByteBuffer) throws -> InboundOut? {
print("Decoder decode: start, buffer readable: \(buffer.readableBytes)")
return nil
}
mutating func decodeLast(buffer: inout NIOCore.ByteBuffer, seenEOF: Bool) throws -> InboundOut? {
print("Decoder decodeLast: start, buffer readable: \(buffer.readableBytes)")
var endSizeText: Int? = nil
let bytesView = buffer.readableBytesView
endSizeText = bytesView.firstIndex(of: UInt8(10))
guard endSizeText != nil else {
print("Decoder decodeLast: newline not found apparently, so asking for more data")
return nil
}
if fileSize == nil {
print("Decoder decodeLast: fileSize is nil, trying to calc. now")
let bytesSubView = buffer.getString (at: 0, length: endSizeText!)
print("Decoder decodeLast: string to convert to int : " + bytesSubView!)
let bytes = UInt64 (bytesSubView ?? "0")
guard bytes != nil else {
// TODO: DEAL W/ THIS
print("Decoder decodeLast: failed to read the integer, so asking for more data")
return nil
}
print("Decoder decodeLast: setting fileSize to \(bytes!), endSizeText is \(endSizeText!)")
fileSize = bytes
}
print("Decoder decodeLast: fileSize is \(fileSize!), readableBytes = \(buffer.readableBytes)")
// if have not read all the bytes that should have been sent, ask for more
// TODO: IMPLEMENT TIME OUT
if fileSize! != buffer.readableBytes - (endSizeText! + 1) {
print("Decoder decodeLast: returning nil, have not read all yet")
return nil
}
print("Decoder decodeLast: at \(endSizeText! + 1) for length \(buffer.readableBytes - (endSizeText! + 1)), readableBytes = \(buffer.readableBytes)")
let outputString = buffer.getString (at: endSizeText! + 1, length: buffer.readableBytes - (endSizeText! + 1))
print("Decoder decodeLast: returning string of length : \(outputString?.count ?? -1)")
// clearing the buffer apparently signals done gathering data
buffer.clear()
return NIOCore.ByteBuffer (string: outputString ?? "")
}
} // RequestDecoder7
Any thoughts, comments, suggestions are greatly appreciated.