// File: davmac314[P]dinit/src/dinitctl.cc
// Function: process_service_event(cpbuffer<1024u>&, unsigned int, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, bool, bool)
static int process_service_event(cpbuffer_t &rbuffer, unsigned pktlen, handle_t handle,
        const std::string &service_name, bool do_stop, bool verbose)
{
    using std::cout;

    // earlier versions do not include status info, the size in that case is
    // base_pkt_size:
    constexpr unsigned base_pkt_size = 2 + sizeof(handle_t) + 1;
    if (pktlen < base_pkt_size) {
        throw dinit_protocol_error();
    }

    // version 5 packets include extended staus info:
    if (rbuffer[0] == (char)cp_info::SERVICEEVENT5 && pktlen < (base_pkt_size + STATUS_BUFFER5_SIZE)) {
        throw dinit_protocol_error();
    }

    service_event_t completion_event;
    service_event_t cancelled_event;
    if (do_stop) {
        completion_event = service_event_t::STOPPED;
        cancelled_event = service_event_t::STOPCANCELLED;
    }
    else {
        completion_event = service_event_t::STARTED;
        cancelled_event = service_event_t::STARTCANCELLED;
    }

    handle_t ev_handle;
    rbuffer.extract((char *)&ev_handle, 2, sizeof(ev_handle));
    service_event_t event = static_cast<service_event_t>(rbuffer[2 + sizeof(ev_handle)]);
    if (ev_handle == handle) {
        if (event == completion_event) {
            if (verbose) {
                cout << "Service '" << service_name << "' " << describe_state(do_stop)
                        << ".\n";
            }
            rbuffer.consume(pktlen);
            return 0;
        }
        else if (event == cancelled_event) {
            if (verbose) {
                cout << "Service '" << service_name << "' " << describe_verb(do_stop)
                        << " cancelled.\n";
            }
            rbuffer.consume(pktlen);
            return 1;
        }
        else if (!do_stop && event == service_event_t::FAILEDSTART) {
            if (verbose) {
                cout << "Service '" << service_name << "' failed to start.\n";
                if (pktlen >= base_pkt_size + STATUS_BUFFER_SIZE) {
                    uint16_t launch_stage;
                    rbuffer.extract((char *)&launch_stage, base_pkt_size + 4,
                                    sizeof(uint16_t));

                    stopped_reason_t stop_reason = static_cast<stopped_reason_t>(rbuffer[base_pkt_size + 3]);
                    int exit_status;
                    int exit_si_code = 0;
                    int exit_si_status = 0;
                    rbuffer.extract((char *)&exit_status, base_pkt_size + 6, sizeof(exit_status));
                    if (rbuffer[0] == (char)cp_info::SERVICEEVENT5) {
                        exit_si_code = exit_status;
                        rbuffer.extract((char *)&exit_si_status,
                                base_pkt_size + 6 + sizeof(exit_si_code), sizeof(exit_si_status));
                    }

                    print_failure_details(stop_reason, launch_stage, exit_status, exit_si_code, exit_si_status);
                }
            }
            rbuffer.consume(pktlen);
            return 1;
        }
    }
    rbuffer.consume(pktlen);
    return -1;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x80, %rsp
movl %r8d, -0x64(%rbp)
movq %rcx, %rax
movl -0x64(%rbp), %ecx
movq %rax, -0x60(%rbp)
movl %edx, %eax
movq -0x60(%rbp), %rdx
movl %eax, -0x54(%rbp)
movl %esi, %eax
movl -0x54(%rbp), %esi
movl %eax, -0x50(%rbp)
movq %rdi, %r8
movl -0x50(%rbp), %edi
movb %r9b, %al
movq %r8, -0x10(%rbp)
movl %edi, -0x14(%rbp)
movl %esi, -0x18(%rbp)
movq %rdx, -0x20(%rbp)
andb $0x1, %cl
movb %cl, -0x21(%rbp)
andb $0x1, %al
movb %al, -0x22(%rbp)
movl $0x7, -0x28(%rbp)
cmpl $0x7, -0x14(%rbp)
jae 0xcf76
movl $0x1, %edi
callq 0x51c0
movq %rax, %rdi
leaq 0x24b73(%rip), %rsi     # 0x31ae0
xorl %eax, %eax
movl %eax, %edx
callq 0x56b0
movq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x113e0
movsbl %al, %eax
cmpl $0x65, %eax
jne 0xcfac
cmpl $0x15, -0x14(%rbp)
jae 0xcfac
movl $0x1, %edi
callq 0x51c0
movq %rax, %rdi
leaq 0x24b3d(%rip), %rsi     # 0x31ae0
xorl %eax, %eax
movl %eax, %edx
callq 0x56b0
testb $0x1, -0x21(%rbp)
je 0xcfc2
movl $0x1, -0x2c(%rbp)
movl $0x4, -0x30(%rbp)
jmp 0xcfd0
movl $0x0, -0x2c(%rbp)
movl $0x3, -0x30(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x34(%rbp), %rsi
movl $0x2, %edx
movl $0x4, %ecx
callq 0x11540
movq -0x10(%rbp), %rdi
movl $0x6, %esi
callq 0x113e0
movsbl %al, %eax
movl %eax, -0x38(%rbp)
movl -0x34(%rbp), %eax
cmpl -0x18(%rbp), %eax
jne 0xd213
movl -0x38(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jne 0xd087
testb $0x1, -0x22(%rbp)
je 0xd06f
movq 0x24f7c(%rip), %rdi     # 0x31f98
leaq 0x17042(%rip), %rsi     # 0x24065
callq 0x53d0
movq %rax, %rdi
movq -0x20(%rbp), %rsi
callq 0x53a0
movq %rax, %rdi
leaq 0x172ea(%rip), %rsi     # 0x24328
callq 0x53d0
movq %rax, -0x70(%rbp)
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %edi
callq 0xc660
movq -0x70(%rbp), %rdi
movq %rax, %rsi
callq 0x53d0
movq %rax, %rdi
leaq 0x1727a(%rip), %rsi     # 0x242e4
callq 0x53d0
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x115f0
movl $0x0, -0x4(%rbp)
jmp 0xd226
movl -0x38(%rbp), %eax
cmpl -0x30(%rbp), %eax
jne 0xd107
testb $0x1, -0x22(%rbp)
je 0xd0ef
movq 0x24efc(%rip), %rdi     # 0x31f98
leaq 0x16fc2(%rip), %rsi     # 0x24065
callq 0x53d0
movq %rax, %rdi
movq -0x20(%rbp), %rsi
callq 0x53a0
movq %rax, %rdi
leaq 0x1726a(%rip), %rsi     # 0x24328
callq 0x53d0
movq %rax, -0x78(%rbp)
movb -0x21(%rbp), %al
andb $0x1, %al
movzbl %al, %edi
callq 0xc980
movq -0x78(%rbp), %rdi
movq %rax, %rsi
callq 0x53d0
movq %rax, %rdi
leaq 0x17241(%rip), %rsi     # 0x2432b
callq 0x53d0
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x115f0
movl $0x1, -0x4(%rbp)
jmp 0xd226
testb $0x1, -0x21(%rbp)
jne 0xd20d
cmpl $0x2, -0x38(%rbp)
jne 0xd20d
testb $0x1, -0x22(%rbp)
je 0xd1f8
movq 0x24e6c(%rip), %rdi     # 0x31f98
leaq 0x16f32(%rip), %rsi     # 0x24065
callq 0x53d0
movq %rax, %rdi
movq -0x20(%rbp), %rsi
callq 0x53a0
movq %rax, %rdi
leaq 0x17058(%rip), %rsi     # 0x241a6
callq 0x53d0
cmpl $0x11, -0x14(%rbp)
jb 0xd1f6
movq -0x10(%rbp), %rdi
leaq -0x3a(%rbp), %rsi
movl $0xb, %edx
movl $0x2, %ecx
callq 0x11540
movq -0x10(%rbp), %rdi
movl $0xa, %esi
callq 0x113e0
movsbl %al, %eax
movl %eax, -0x40(%rbp)
movl $0x0, -0x48(%rbp)
movl $0x0, -0x4c(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x44(%rbp), %rsi
movl $0xd, %edx
movl $0x4, %ecx
callq 0x11540
movq -0x10(%rbp), %rdi
xorl %esi, %esi
callq 0x113e0
movsbl %al, %eax
cmpl $0x65, %eax
jne 0xd1dd
movl -0x44(%rbp), %eax
movl %eax, -0x48(%rbp)
movq -0x10(%rbp), %rdi
leaq -0x4c(%rbp), %rsi
movl $0x11, %edx
movl $0x4, %ecx
callq 0x11540
movl -0x40(%rbp), %edi
movw -0x3a(%rbp), %ax
movl -0x44(%rbp), %edx
movl -0x48(%rbp), %ecx
movl -0x4c(%rbp), %r8d
movzwl %ax, %esi
callq 0xcb50
jmp 0xd1f8
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x115f0
movl $0x1, -0x4(%rbp)
jmp 0xd226
jmp 0xd20f
jmp 0xd211
jmp 0xd213
movq -0x10(%rbp), %rdi
movl -0x14(%rbp), %esi
callq 0x115f0
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
movl -0x4(%rbp), %eax
addq $0x80, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)