Lea exactamente n bytes de InputStream en Swift 4

Tengo un servidor que me envía mensajes a través de TCP donde los primeros 4 bytes determinan la longitud del resto del mensaje. Entonces necesito

1) leer 4 bytes en un UInt32 (funciona) y almacenarlo enbytes_esperados

2) leerbytes_esperados bytes enmensaje

En este momento mi código se ve así:

private let inputStreamAccessQueue  = DispatchQueue(label: "SynchronizedInputStreamAccess")
func inputStreamHandler(_ event: Stream.Event) {
    switch event {
        case Stream.Event.hasBytesAvailable:
            self.handleInput()

        ...
    }
}
func handleInput() {
    // **QUESTION: Do I use this barrier wrong?**
    self.inputStreamAccessQueue.sync(flags: .barrier) {            
        guard let istr = self.inputStream else {
            log.error(self.buildLogMessage("InputStream is nil"))
            return
        }

        guard istr.hasBytesAvailable else {
            log.error(self.buildLogMessage("handleInput() called when inputstream has no bytes available"))
            return
        }

        let lengthbuffer = UnsafeMutablePointer<UInt8>.allocate(capacity: 4)
        defer { lengthbuffer.deallocate(capacity: 4) }
        let lenbytes_read = istr.read(lengthbuffer, maxLength: 4)

        guard lenbytes_read == 4 else {
            self.errorHandler(NetworkingError.InputError("Input Stream received \(lenbytes_read) (!=4) bytes"))
            return
        }

        let bytes_expected = Int(UnsafeRawPointer(lengthbuffer).load(as: UInt32.self).bigEndian)
        log.info(self.buildLogMessage("expect \(bytes_expected) bytes"))

        print("::DEBUG", call, "bytes_expected", bytes_expected)

        var message = ""
        var bytes_missing = bytes_expected
        while bytes_missing > 0 {
            //print("::DEBUG", call, "bytes_missing", bytes_missing)
            let buffer = UnsafeMutablePointer<UInt8>.allocate(capacity: bytes_missing)
            let bytes_read = istr.read(buffer, maxLength: bytes_missing)

            print("::DEBUG", call, "bytes_read", bytes_read)

            guard bytes_read > 0 else {
                print("bytes_read not > 0: \(bytes_read)")
                return
            }

            guard bytes_read <= bytes_missing else {
                print("Read more bytes than expected. missing=\(bytes_missing), read=\(bytes_read)")
                return
            }

            guard let partial_message = String(bytesNoCopy: buffer, length: bytes_read, encoding: .utf8, freeWhenDone: true) else {
                log.error("ERROR WHEN READING")
                return
            }

            message = message + partial_message
            bytes_missing -= bytes_read
        }

        self.handleMessage(message)
    }
}

Mi problema es que istr.read (buffer, maxLength: bytes_missing) a veces no lee todos los mensajes a la vez, por lo que hago un bucle hasta que haya leído todo lo que quiero. Pero todavía veo que mi aplicación falla (raramente) porque se vuelve a llamar a handleInput () mientras aún se está ejecutando otra llamada a ese método. En este caso, bytes_esperados contiene valores aleatorios y la aplicación se bloquea debido a la asignación ilegal de memoria.

Pensé que podría evitar esto usando la barrera. Pero parece que esto no funciona ... ¿Estoy usando mal la barrera?

Respuestas a la pregunta(2)

Su respuesta a la pregunta