// File: davmac314[P]dinit/src/control.cc
// Function: control_conn_t::queue_packet(char const*, unsigned int)
bool control_conn_t::queue_packet(const char *pkt, unsigned size) noexcept
{
    bool was_empty = outbuf.empty();

    // If the queue is empty, we can try to write the packet out now rather than queueing it.
    // If the write is unsuccessful or partial, we queue the remainder.
    if (was_empty) {
        int wr = bp_sys::write(iob.get_watched_fd(), pkt, size);
        if (wr == -1) {
            if (errno == EPIPE) {
                return false;
            }
            if (errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
                log(loglevel_t::WARN, "Error writing to control connection: ", strerror(errno));
                return false;
            }
            // EAGAIN etc: fall through to below
        }
        else {
            if ((unsigned)wr == size) {
                // Ok, all written.
                return true;
            }
            pkt += wr;
            size -= wr;
        }
    }
    
    // Create a vector out of the (remaining part of the) packet:
    try {
        outbuf.emplace_back(pkt, pkt + size);
        outbuf_size += size;
        return true;
    }
    catch (std::bad_alloc &baexc) {
        // Mark the connection bad, and stop reading further requests
        bad_conn_close = true;
        oom_close = true;
        if (was_empty) {
            // We can't send out-of-memory response as we already wrote as much as we
            // could above. Neither can we later send the response since we have currently
            // sent an incomplete packet. All we can do is close the connection.
            return false;
        }
        else {
            return true;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x60(%rbp)
addq $0x4f0, %rdi            # imm = 0x4F0
callq 0x11bd0
andb $0x1, %al
movb %al, -0x1d(%rbp)
testb $0x1, -0x1d(%rbp)
je 0x5843c
movq -0x60(%rbp), %rdi
addq $0x10, %rdi
callq 0x5fb70
movl %eax, -0x64(%rbp)
jmp 0x58388
movl -0x64(%rbp), %edi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %eax
movl %eax, %edx
callq 0xa200
movq %rax, -0x70(%rbp)
jmp 0x5839f
movq -0x70(%rbp), %rax
movl %eax, -0x24(%rbp)
cmpl $-0x1, -0x24(%rbp)
jne 0x5840d
callq 0xa060
cmpl $0x20, (%rax)
jne 0x583bf
movb $0x0, -0x1(%rbp)
jmp 0x584d8
callq 0xa060
cmpl $0xb, (%rax)
je 0x5840b
callq 0xa060
cmpl $0xb, (%rax)
je 0x5840b
callq 0xa060
cmpl $0x4, (%rax)
je 0x5840b
callq 0xa060
movl (%rax), %edi
callq 0xa1f0
movq %rax, -0x30(%rbp)
movl $0x2, %edi
leaq 0x210e8(%rip), %rsi     # 0x794e1
leaq -0x30(%rbp), %rdx
callq 0x5cc20
movb $0x0, -0x1(%rbp)
jmp 0x584d8
jmp 0x5843a
movl -0x24(%rbp), %eax
cmpl -0x1c(%rbp), %eax
jne 0x5841e
movb $0x1, -0x1(%rbp)
jmp 0x584d8
movl -0x24(%rbp), %ecx
movq -0x18(%rbp), %rax
movslq %ecx, %rcx
addq %rcx, %rax
movq %rax, -0x18(%rbp)
movl -0x24(%rbp), %ecx
movl -0x1c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x1c(%rbp)
jmp 0x5843c
movq -0x60(%rbp), %rdi
addq $0x4f0, %rdi            # imm = 0x4F0
movq -0x18(%rbp), %rax
movl -0x1c(%rbp), %ecx
addq %rcx, %rax
movq %rax, -0x38(%rbp)
leaq -0x18(%rbp), %rsi
leaq -0x38(%rbp), %rdx
callq 0x5fb90
jmp 0x58464
movq -0x60(%rbp), %rax
movl -0x1c(%rbp), %ecx
addl 0x508(%rax), %ecx
movl %ecx, 0x508(%rax)
movb $0x1, -0x1(%rbp)
jmp 0x584d8
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x40(%rbp)
movl %eax, -0x44(%rbp)
movl -0x44(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x584eb
movq -0x40(%rbp), %rdi
callq 0xa240
movq %rax, %rcx
movq -0x60(%rbp), %rax
movq %rcx, -0x50(%rbp)
movb $0x1, 0x78(%rax)
movb $0x1, 0x79(%rax)
testb $0x1, -0x1d(%rbp)
je 0x584c4
movb $0x0, -0x1(%rbp)
movl $0x1, -0x54(%rbp)
jmp 0x584cf
movb $0x1, -0x1(%rbp)
movl $0x1, -0x54(%rbp)
callq 0xac30
jmp 0x584d6
jmp 0x584d8
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x70, %rsp
popq %rbp
retq
movq %rax, %rdi
callq 0xfa30
movq -0x40(%rbp), %rdi
callq 0xfa30
nopw %cs:(%rax,%rax)