func readFromSocket()

in Sources/NIOPosix/DatagramVectorReadManager.swift [92:143]


    func readFromSocket(socket: Socket,
                        buffer: inout ByteBuffer,
                        parseControlMessages: Bool) throws -> ReadResult {
        assert(buffer.readerIndex == 0, "Buffer was not cleared between calls to readFromSocket!")

        let messageSize = buffer.capacity / self.messageCount

        let result = try buffer.withVeryUnsafeMutableBytes { bufferPointer -> IOResult<Int> in
            for i in 0..<self.messageCount {
                // TODO(cory): almost all of this except for the iovec could be done at allocation time. Maybe we should?

                // First we set up the iovec and save it off.
                self.ioVector[i] = IOVector(iov_base: bufferPointer.baseAddress! + (i * messageSize), iov_len: numericCast(messageSize))
                
                let controlBytes: UnsafeMutableRawBufferPointer
                if parseControlMessages {
                    // This will be used in buildMessages below but should not be used beyond return of this function.
                    controlBytes = self.controlMessageStorage[i]
                } else {
                    controlBytes = UnsafeMutableRawBufferPointer(start: nil, count: 0)
                }

                // Next we set up the msghdr structure. This points into the other vectors.
                let msgHdr = msghdr(msg_name: self.sockaddrVector.baseAddress! + i ,
                                    msg_namelen: socklen_t(MemoryLayout<sockaddr_storage>.size),
                                    msg_iov: self.ioVector.baseAddress! + i,
                                    msg_iovlen: 1,  // This is weird, but each message gets only one array. Duh.
                                    msg_control: controlBytes.baseAddress,
                                    msg_controllen: .init(controlBytes.count),
                                    msg_flags: 0)
                self.messageVector[i] = MMsgHdr(msg_hdr: msgHdr, msg_len: 0)

                // Note that we don't set up the sockaddr vector: that's because it needs no initialization,
                // it's written into by the kernel.
            }

            // We've set up our pointers, it's time to get going. We now issue the call.
            return try socket.recvmmsg(msgs: self.messageVector)
        }

        switch result {
        case .wouldBlock(let messagesProcessed):
            assert(messagesProcessed == 0)
            return .none
        case .processed(let messagesProcessed):
            buffer.moveWriterIndex(to: messageSize * messagesProcessed)
            return self.buildMessages(messageCount: messagesProcessed,
                                      sliceSize: messageSize,
                                      buffer: &buffer,
                                      parseControlMessages: parseControlMessages)
        }
    }