// File: davmac314[P]dinit/src/control.cc
// Function: control_conn_t::process_packet()
bool control_conn_t::process_packet()
{
    using std::string;
    
    // Note that where we call queue_packet, we must generally check the return value. If it
    // returns false it has either deleted the connection or marked it for deletion; we
    // shouldn't touch instance members after that point.

    cp_cmd pkt_type = (cp_cmd)rbuf[0];

    switch (pkt_type) {
        case cp_cmd::QUERYVERSION:
        {
            // Responds with:
            // cp_rply::CPVERSION, (2 byte) minimum compatible version, (2 byte) actual version
            char replyBuf[] = { (char)cp_rply::CPVERSION, 0, 0, 0, 0 };
            memcpy(replyBuf + 1, &min_compat_version, 2);
            memcpy(replyBuf + 3, &cp_version, 2);
            if (!queue_packet(replyBuf, sizeof(replyBuf))) return false;
            rbuf.consume(1);
            return true;
        }
        case cp_cmd::FINDSERVICE:
        case cp_cmd::LOADSERVICE:
            return process_find_load(pkt_type);
        case cp_cmd::CLOSEHANDLE:
            return process_close_handle();
        case cp_cmd::STARTSERVICE:
        case cp_cmd::STOPSERVICE:
        case cp_cmd::WAKESERVICE:
        case cp_cmd::RELEASESERVICE:
            return process_start_stop(pkt_type);
        case cp_cmd::UNPINSERVICE:
            return process_unpin_service();
        case cp_cmd::UNLOADSERVICE:
            return process_unload_service();
        case cp_cmd::RELOADSERVICE:
            return process_reload_service();
        case cp_cmd::SHUTDOWN:
            // Shutdown/reboot
            if (rbuf.get_length() < 2) {
                chklen = 2;
                return true;
            }

            if (contains({shutdown_type_t::REMAIN, shutdown_type_t::HALT,
                    shutdown_type_t::POWEROFF, shutdown_type_t::REBOOT,
                    shutdown_type_t::SOFTREBOOT, shutdown_type_t::KEXEC}, rbuf[1])) {
                auto sd_type = static_cast<shutdown_type_t>(rbuf[1]);

                services->stop_all_services(sd_type);
                char ackBuf[] = { (char)cp_rply::ACK };
                if (! queue_packet(ackBuf, 1)) return false;

                // Clear the packet from the buffer
                rbuf.consume(2);
                chklen = 0;
                return true;
            }

            break;
        case cp_cmd::LISTSERVICES:
            return list_services();
        case cp_cmd::LISTSERVICES5:
            return list_services5();
        case cp_cmd::SERVICESTATUS:
            return process_service_status();
        case cp_cmd::SERVICESTATUS5:
            return process_service_status5();
        case cp_cmd::ADD_DEP:
            return add_service_dep();
        case cp_cmd::REM_DEP:
            return rm_service_dep();
        case cp_cmd::QUERY_LOAD_MECH:
            return query_load_mech();
        case cp_cmd::ENABLESERVICE:
            return add_service_dep(true);
        case cp_cmd::QUERYSERVICENAME:
            return process_query_name();
        case cp_cmd::SETENV:
            return process_setenv();
        case cp_cmd::GETALLENV:
            return process_getallenv();
        case cp_cmd::LISTENENV:
            return process_listenenv();
        case cp_cmd::SETTRIGGER:
            return process_set_trigger();
        case cp_cmd::CATLOG:
            return process_catlog();
        case cp_cmd::SIGNAL:
            return process_signal();
        case cp_cmd::QUERYSERVICEDSCDIR:
            return process_query_dsc_dir();
        default:
            break;
    }

    // Unrecognized: give error response
    char outbuf[] = { (char)cp_rply::BADREQ };
    if (!queue_packet(outbuf, 1)) return false;
    bad_conn_close = true;
    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x30(%rbp)
subq $-0x80, %rdi
xorl %esi, %esi
callq 0x5e160
movb %al, -0x11(%rbp)
movzbl -0x11(%rbp), %eax
movq %rax, -0x28(%rbp)
subq $0x1b, %rax
ja 0x582f8
movq -0x28(%rbp), %rax
leaq 0x21381(%rip), %rcx     # 0x79380
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x30(%rbp), %rdi
movl 0x2141e(%rip), %eax     # 0x79430
movl %eax, -0x16(%rbp)
movb 0x21419(%rip), %al      # 0x79434
movb %al, -0x12(%rbp)
movw 0x21411(%rip), %ax      # 0x79436
movw %ax, -0x15(%rbp)
movw 0x21408(%rip), %ax      # 0x79438
movw %ax, -0x13(%rbp)
leaq -0x16(%rbp), %rsi
movl $0x5, %edx
callq 0x58340
testb $0x1, %al
jne 0x5804f
movb $0x0, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
addq $0x80, %rdi
movl $0x1, %esi
callq 0x5e1a0
movb $0x1, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
movzbl -0x11(%rbp), %esi
callq 0x58500
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x58aa0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
movzbl -0x11(%rbp), %esi
callq 0x58ce0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x591d0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x592f0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x59480
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
addq $0x80, %rdi
callq 0x5e200
cmpl $0x2, %eax
jae 0x58110
movq -0x30(%rbp), %rax
movl $0x2, 0x7c(%rax)
movb $0x1, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
movb $0x1, -0x1c(%rbp)
movb $0x2, -0x1b(%rbp)
movb $0x3, -0x1a(%rbp)
movb $0x4, -0x19(%rbp)
movb $0x5, -0x18(%rbp)
movb $0x6, -0x17(%rbp)
addq $0x80, %rdi
movl $0x1, %esi
callq 0x5e160
leaq -0x1c(%rbp), %rdi
movsbl %al, %esi
callq 0x596d0
testb $0x1, %al
jne 0x5814f
jmp 0x581cb
movq -0x30(%rbp), %rdi
addq $0x80, %rdi
movl $0x1, %esi
callq 0x5e160
movb %al, %cl
movq -0x30(%rbp), %rax
movb %cl, -0x1d(%rbp)
movq 0x70(%rax), %rdi
movsbl -0x1d(%rbp), %esi
callq 0x17b60
movq -0x30(%rbp), %rdi
movb 0x212b6(%rip), %al      # 0x7943a
movb %al, -0x1e(%rbp)
leaq -0x1e(%rbp), %rsi
movl $0x1, %edx
callq 0x58340
testb $0x1, %al
jne 0x581a2
movb $0x0, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
addq $0x80, %rdi
movl $0x2, %esi
callq 0x5e1a0
movq -0x30(%rbp), %rax
movl $0x0, 0x7c(%rax)
movb $0x1, -0x1(%rbp)
jmp 0x5832b
jmp 0x582fa
movq -0x30(%rbp), %rdi
callq 0x59730
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x59a40
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x59d50
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x59f00
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
xorl %esi, %esi
callq 0x5a0b0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5a770
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5a970
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
movl $0x1, %esi
callq 0x5a0b0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5ace0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5aea0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5b0d0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5b3a0
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5b400
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5b540
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5b880
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rdi
callq 0x5ba60
andb $0x1, %al
movb %al, -0x1(%rbp)
jmp 0x5832b
jmp 0x582fa
movq -0x30(%rbp), %rdi
movb 0x21137(%rip), %al      # 0x7943b
movb %al, -0x1f(%rbp)
leaq -0x1f(%rbp), %rsi
movl $0x1, %edx
callq 0x58340
testb $0x1, %al
jne 0x5831f
movb $0x0, -0x1(%rbp)
jmp 0x5832b
movq -0x30(%rbp), %rax
movb $0x1, 0x78(%rax)
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x30, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)