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.