// File: davmac314[P]dinit/src/control.cc
// Function: control_conn_t::service_event(service_record*, service_event_t)
void control_conn_t::service_event(service_record *service, service_event_t event) noexcept
{
    // For each service handle corresponding to the event, send an information packet.
    auto range = service_key_map.equal_range(service);
    auto &i = range.first;
    auto &end = range.second;
    try {
        while (i != end) {
            uint32_t key = i->second;
            std::vector<char> pkt;

            // There are two types of service event packet: v5+, and the original. For backwards
            // compatibility, we send both. The new packet is sent first since this simplifies
            // things for the client (eg if waiting for an event, the client will receive the
            // packet with the most information first).

            // packet type (byte) + packet length (byte) + event type (byte) + key + status buffer
            constexpr int pktsize5 = 3 + sizeof(key) + STATUS_BUFFER5_SIZE;
            pkt.reserve(pktsize5);
            pkt.push_back((char)cp_info::SERVICEEVENT5);
            pkt.push_back(pktsize5);
            char *p = (char *)&key;
            for (unsigned j = 0; j < sizeof(key); j++) {
                pkt.push_back(*p++);
            }
            pkt.push_back(static_cast<char>(event));
            pkt.resize(pktsize5);
            fill_status_buffer5(pkt.data() + 3 + sizeof(key), service);
            queue_packet(std::move(pkt));

            pkt.clear();

            constexpr int pktsize = 3 + sizeof(key) + STATUS_BUFFER_SIZE;
            pkt.reserve(pktsize);
            pkt.push_back((char)cp_info::SERVICEEVENT);
            pkt.push_back(pktsize);
            p = (char *)&key;
            for (unsigned j = 0; j < sizeof(key); j++) {
                pkt.push_back(*p++);
            }
            pkt.push_back(static_cast<char>(event));
            pkt.resize(pktsize);
            fill_status_buffer(pkt.data() + 3 + sizeof(key), service);
            queue_packet(std::move(pkt));

            ++i;
        }
    }
    catch (std::bad_alloc &exc) {
        do_oom_close();
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xc0, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movl %edx, -0x14(%rbp)
movq -0x8(%rbp), %rdi
movq %rdi, -0xb0(%rbp)
addq $0x488, %rdi            # imm = 0x488
leaq -0x10(%rbp), %rsi
callq 0x5e790
movq %rdx, -0xa8(%rbp)
movq %rax, -0xa0(%rbp)
jmp 0x5c761
movq -0xa8(%rbp), %rax
movq -0xa0(%rbp), %rcx
movq %rcx, -0x28(%rbp)
movq %rax, -0x20(%rbp)
leaq -0x28(%rbp), %rax
movq %rax, -0x30(%rbp)
leaq -0x28(%rbp), %rax
addq $0x8, %rax
movq %rax, -0x38(%rbp)
movq -0x30(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x5e830
testb $0x1, %al
jne 0x5c7a1
jmp 0x5c9fa
movq -0x30(%rbp), %rdi
callq 0x5e7d0
movl 0x8(%rax), %eax
movl %eax, -0x3c(%rbp)
leaq -0x58(%rbp), %rdi
movq %rdi, -0xb8(%rbp)
callq 0x30d60
movq -0xb8(%rbp), %rdi
movl $0x15, -0x5c(%rbp)
movl $0x15, %esi
callq 0x5e520
jmp 0x5c7da
movb $0x65, -0x6d(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x6d(%rbp), %rsi
callq 0x5e600
jmp 0x5c7ed
movb $0x15, -0x6e(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x6e(%rbp), %rsi
callq 0x5e600
jmp 0x5c800
leaq -0x3c(%rbp), %rax
movq %rax, -0x78(%rbp)
movl $0x0, -0x7c(%rbp)
movl -0x7c(%rbp), %eax
cmpq $0x4, %rax
jae 0x5c891
movq -0x78(%rbp), %rsi
movq %rsi, %rax
incq %rax
movq %rax, -0x78(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x5e630
jmp 0x5c831
jmp 0x5c833
movl -0x7c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x7c(%rbp)
jmp 0x5c80f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x68(%rbp)
movl %eax, -0x6c(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x13f20
movl -0x6c(%rbp), %eax
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x5ca07
movq -0x68(%rbp), %rdi
callq 0xa240
movq -0xb0(%rbp), %rdi
movq %rax, -0x98(%rbp)
callq 0x5eff0
callq 0xac30
jmp 0x5c886
jmp 0x5c888
addq $0xc0, %rsp
popq %rbp
retq
movb -0x14(%rbp), %al
movb %al, -0x7d(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x7d(%rbp), %rsi
callq 0x5e600
jmp 0x5c8a6
leaq -0x58(%rbp), %rdi
movl $0x15, %esi
callq 0x31490
jmp 0x5c8b6
leaq -0x58(%rbp), %rdi
callq 0x31180
movq %rax, %rdi
addq $0x7, %rdi
movq -0x10(%rbp), %rsi
callq 0x5c450
jmp 0x5c8d1
movq -0xb0(%rbp), %rdi
leaq -0x58(%rbp), %rsi
movq %rsi, -0xc0(%rbp)
callq 0x5bc70
movq -0xc0(%rbp), %rdi
callq 0x5fb50
movq -0xc0(%rbp), %rdi
movl $0x11, -0x84(%rbp)
movl $0x11, %esi
callq 0x5e520
jmp 0x5c911
movb $0x64, -0x85(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x85(%rbp), %rsi
callq 0x5e600
jmp 0x5c92a
movb $0x11, -0x86(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x86(%rbp), %rsi
callq 0x5e600
jmp 0x5c943
leaq -0x3c(%rbp), %rax
movq %rax, -0x78(%rbp)
movl $0x0, -0x8c(%rbp)
movl -0x8c(%rbp), %eax
cmpq $0x4, %rax
jae 0x5c98d
movq -0x78(%rbp), %rsi
movq %rsi, %rax
incq %rax
movq %rax, -0x78(%rbp)
leaq -0x58(%rbp), %rdi
callq 0x5e630
jmp 0x5c97a
jmp 0x5c97c
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
jmp 0x5c955
movb -0x14(%rbp), %al
movb %al, -0x8d(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x8d(%rbp), %rsi
callq 0x5e600
jmp 0x5c9a8
leaq -0x58(%rbp), %rdi
movl $0x11, %esi
callq 0x31490
jmp 0x5c9b8
leaq -0x58(%rbp), %rdi
callq 0x31180
movq %rax, %rdi
addq $0x7, %rdi
movq -0x10(%rbp), %rsi
callq 0x5c2b0
jmp 0x5c9d3
movq -0xb0(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x5bc70
movq -0x30(%rbp), %rdi
callq 0x5e800
leaq -0x58(%rbp), %rdi
callq 0x13f20
jmp 0x5c78b
jmp 0x5c888
movq %rax, %rdi
callq 0xfa30
movq -0x68(%rbp), %rdi
callq 0xfa30