// File: /workspace/github_c_makefile_star2_O1/zuocheng-liu[P]ae-memcached/src/memcached.c
// Function: drive_machine
void drive_machine(conn *c) {

    int exit = 0;
    int sfd, flags = 1;
    socklen_t addrlen;
    struct sockaddr addr;
    conn *newc;
    int res;

    while (!exit) {
        switch(c->state) {
        case conn_listening:
            addrlen = sizeof(addr);
            if ((sfd = accept(c->sfd, &addr, &addrlen)) == -1) {
                if (errno == EAGAIN || errno == EWOULDBLOCK) {
                    exit = 1;
                    break;
                } else {
                    perror("accept()");
                }
                break;
            }
            if ((flags = fcntl(sfd, F_GETFL, 0)) < 0 ||
                fcntl(sfd, F_SETFL, flags | O_NONBLOCK) < 0) {
                perror("setting O_NONBLOCK");
                close(sfd);
                break;
            }
            newc = conn_new(sfd, conn_read, AE_READABLE, DATA_BUFFER_SIZE, 0);
            if (!newc) {
                LOG_INFO("Couldn't create new connection\n");
                close(sfd);
                break;
            }

            break;

        case conn_read:
            if (try_read_command(c)) {
                continue;
            }
            if (c->udp ? try_read_udp(c) : try_read_network(c)) {
                continue;
            }
            /* we have no command line and no data to read from network */
            if (!update_event(c, AE_READABLE)) {
                LOG_INFO("Couldn't update event\n");
                conn_set_state(c, conn_closing);
                break;
            }
            exit = 1;
            break;

        case conn_nread:
            /* we are reading rlbytes into ritem; */
            if (c->rlbytes == 0) {
                complete_nread(c);
                break;
            }
            /* first check if we have leftovers in the conn_read buffer */
            if (c->rbytes > 0) {
                int tocopy = c->rbytes > c->rlbytes ? c->rlbytes : c->rbytes;
                memcpy(c->ritem, c->rcurr, tocopy);
                c->ritem += tocopy;
                c->rlbytes -= tocopy;
                c->rcurr += tocopy;
                c->rbytes -= tocopy;
                break;
            }

            /*  now try reading from the socket */
            res = read(c->sfd, c->ritem, c->rlbytes);
            if (res > 0) {
                stats.bytes_read += res;
                c->ritem += res;
                c->rlbytes -= res;
                break;
            }
            if (res == 0) { /* end of stream */
                conn_set_state(c, conn_closing);
                break;
            }
            if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                if (!update_event(c, AE_READABLE)) {
                    LOG_INFO("Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                exit = 1;
                break;
            }
            /* otherwise we have a real error, on which we close the connection */
            LOG_INFO("Failed to read, and not due to blocking\n");
            conn_set_state(c, conn_closing);
            break;

        case conn_swallow:
            /* we are reading sbytes and throwing them away */
            if (c->sbytes == 0) {
                conn_set_state(c, conn_read);
                break;
            }

            /* first check if we have leftovers in the conn_read buffer */
            if (c->rbytes > 0) {
                int tocopy = c->rbytes > c->sbytes ? c->sbytes : c->rbytes;
                c->sbytes -= tocopy;
                c->rcurr += tocopy;
                c->rbytes -= tocopy;
                break;
            }

            /*  now try reading from the socket */
            res = read(c->sfd, c->rbuf, c->rsize > c->sbytes ? c->sbytes : c->rsize);
            if (res > 0) {
                stats.bytes_read += res;
                c->sbytes -= res;
                break;
            }
            if (res == 0) { /* end of stream */
                conn_set_state(c, conn_closing);
                break;
            }
            if (res == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
                if (!update_event(c, AE_READABLE)) {
                    LOG_INFO("Couldn't update event\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
                exit = 1;
                break;
            }
            /* otherwise we have a real error, on which we close the connection */
            LOG_INFO("Failed to read, and not due to blocking\n");
            conn_set_state(c, conn_closing);
            break;

        case conn_write:
            /*
             * We want to write out a simple response. If we haven't already,
             * assemble it into a msgbuf list (this will be a single-entry
             * list for TCP or a two-entry list for UDP).
             */
            if (c->iovused == 0) {
                if (add_iov(c, c->wcurr, c->wbytes) ||
                        (c->udp && build_udp_headers(c))) {
                    LOG_INFO("Couldn't build response\n");
                    conn_set_state(c, conn_closing);
                    break;
                }
            }

            /* fall through... */

        case conn_mwrite:
            switch (transmit(c)) {
            case TRANSMIT_COMPLETE:
                if (c->state == conn_mwrite) {
                    while (c->ileft > 0) {
                        item *it = *(c->icurr);
                        assert((it->it_flags & ITEM_SLABBED) == 0);
                        item_remove(it);
                        c->icurr++;
                        c->ileft--;
                    }
                    conn_set_state(c, conn_read);
                } else if (c->state == conn_write) {
                    if (c->write_and_free) {
                        free(c->write_and_free);
                        c->write_and_free = 0;
                    }
                    conn_set_state(c, c->write_and_go);
                } else {
                    LOG_INFO_F1("Unexpected state %d\n", c->state);
                    conn_set_state(c, conn_closing);
                }
                break;

            case TRANSMIT_INCOMPLETE:
            case TRANSMIT_HARD_ERROR:
                break;                   /* Continue in state machine. */

            case TRANSMIT_SOFT_ERROR:
                exit = 1;
                break;
            }
            break;

        case conn_closing:
            if (c->udp)
                conn_cleanup(c);
            else
                conn_close(c);
            exit = 1;
            break;
        }

    }

    return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %rbx
movb $0x1, %r12b
leaq 0x1c4e(%rip), %r13      # 0x8348
leaq 0x8(%rsp), %r14
leaq 0x4(%rsp), %r15
xorl %ebp, %ebp
movl 0x4(%rbx), %eax
cmpl $0x1, %eax
jne 0x6738
movq %rbx, %rdi
callq 0x62dd
testl %eax, %eax
jne 0x67f2
cmpl $0x0, 0xbc(%rbx)
je 0x67e2
movq %rbx, %rdi
callq 0x6352
jmp 0x67ea
cmpl $0x6, %eax
ja 0x6a5b
movl %eax, %eax
movslq (%r13,%rax,4), %rax
addq %r13, %rax
jmpq *%rax
movl $0x10, 0x4(%rsp)
movl (%rbx), %edi
movq %r14, %rsi
movq %r15, %rdx
callq 0x23d0
cmpl $-0x1, %eax
je 0x690d
movl %eax, %r12d
movl %eax, %edi
movl $0x3, %esi
xorl %edx, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x6aae
orl $0x800, %eax            # imm = 0x800
movl %r12d, %edi
movl $0x4, %esi
movl %eax, %edx
xorl %eax, %eax
callq 0x20f0
testl %eax, %eax
js 0x6aae
movl %r12d, %edi
movl $0x1, %esi
movl $0x1, %edx
movl $0x800, %ecx            # imm = 0x800
xorl %r8d, %r8d
callq 0x3b80
testq %rax, %rax
jne 0x6a5b
leaq 0x6aba(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6aba
callq 0x26da
jmp 0x6aba
movq %rbx, %rdi
callq 0x63f5
testl %eax, %eax
je 0x6984
testb $0x1, %r12b
jne 0x6706
jmp 0x6b97
movslq 0x60(%rbx), %rdx
testq %rdx, %rdx
je 0x6932
movl 0x2c(%rbx), %eax
testl %eax, %eax
jle 0x69ba
cmpl %edx, %eax
cmovll %eax, %edx
movq 0x20(%rbx), %rsi
movq 0x58(%rbx), %rdi
movslq %edx, %r12
movq %r12, %rdx
callq 0x2280
addq %r12, 0x58(%rbx)
subl %r12d, 0x60(%rbx)
addq %r12, 0x20(%rbx)
subl %r12d, 0x2c(%rbx)
jmp 0x6a5b
cmpl $0x0, 0x84(%rbx)
je 0x693f
movq %rbx, %rdi
callq 0x65a5
cmpl $0x2, %eax
je 0x6979
testl %eax, %eax
jne 0x6a5b
movl 0x4(%rbx), %edx
cmpl $0x2, %edx
je 0x6a1f
cmpl $0x6, %edx
jne 0x6a3d
cmpl $0x0, 0xb8(%rbx)
jle 0x6900
movq 0xb0(%rbx), %rax
movq (%rax), %rdi
callq 0x489f
addq $0x8, 0xb0(%rbx)
movl 0xb8(%rbx), %eax
leal -0x1(%rax), %ecx
movl %ecx, 0xb8(%rbx)
cmpl $0x1, %eax
jg 0x688a
jmp 0x6900
cmpl $0x0, 0xbc(%rbx)
je 0x6971
movq %rbx, %rdi
callq 0x3ee9
jmp 0x6979
movl 0x74(%rbx), %eax
testl %eax, %eax
je 0x6900
movl 0x2c(%rbx), %ecx
testl %ecx, %ecx
jle 0x69e9
cmpl %eax, %ecx
movl %eax, %edx
cmovll %ecx, %edx
subl %edx, %eax
movl %eax, 0x74(%rbx)
movslq %edx, %rax
addq %rax, 0x20(%rbx)
subl %eax, %ecx
movl %ecx, 0x2c(%rbx)
jmp 0x6a5b
movq %rbx, %rdi
movl $0x1, %esi
jmp 0x6a56
callq 0x2040
movl $0x1, %r12d
cmpl $0xb, (%rax)
je 0x6a5e
leaq 0x1ff8(%rip), %rdi      # 0x8920
callq 0x23b0
jmp 0x6a5b
movq %rbx, %rdi
callq 0x50c9
jmp 0x6a5b
movq 0x38(%rbx), %rsi
movl 0x44(%rbx), %edx
movq %rbx, %rdi
callq 0x4265
testl %eax, %eax
je 0x6a73
leaq 0x692b(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x260e
jmp 0x6a4e
movq %rbx, %rdi
callq 0x3f58
movl $0x1, %r12d
jmp 0x6a5e
movl $0x1, %r12d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x6535
testl %eax, %eax
jne 0x6a5e
leaq 0x68e2(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x26b8
jmp 0x6a4e
movl (%rbx), %edi
movq 0x58(%rbx), %rsi
callq 0x21f0
testl %eax, %eax
jle 0x6a95
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x6904(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
addq %rcx, 0x58(%rbx)
subl %eax, 0x60(%rbx)
jmp 0x6a5b
movl (%rbx), %edi
movq 0x18(%rbx), %rsi
movl 0x28(%rbx), %ecx
cmpl %eax, %ecx
cmovll %ecx, %eax
movslq %eax, %rdx
callq 0x21f0
testl %eax, %eax
jle 0x6aa0
movl %eax, %ecx
andl $0x7fffffff, %ecx       # imm = 0x7FFFFFFF
leaq 0x68ca(%rip), %rdx      # 0xd2e0
addq %rcx, 0x48(%rdx)
subl %eax, 0x74(%rbx)
jmp 0x6a5b
movq 0x50(%rbx), %rdi
testq %rdi, %rdi
je 0x6a35
callq 0x2030
movq $0x0, 0x50(%rbx)
movl 0x48(%rbx), %esi
movq %rbx, %rdi
jmp 0x6a56
leaq 0x6844(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jg 0x6b7a
movq %rbx, %rdi
movl $0x5, %esi
callq 0x41a2
movl %ebp, %r12d
movl %r12d, %ebp
testl %r12d, %r12d
sete %r12b
je 0x6706
jmp 0x6b97
cmpl $0x0, 0xbc(%rbx)
je 0x6853
movq %rbx, %rdi
callq 0x4fc7
testl %eax, %eax
jne 0x6956
jmp 0x6853
cmpl $-0x1, %eax
je 0x6ac4
testl %eax, %eax
je 0x6a4e
jmp 0x6b04
cmpl $-0x1, %eax
je 0x6b1f
testl %eax, %eax
je 0x6a4e
jmp 0x6b5f
leaq 0x1e74(%rip), %rdi      # 0x8929
callq 0x23b0
movl %r12d, %edi
callq 0x21b0
jmp 0x6a5b
callq 0x2040
cmpl $0xb, (%rax)
jne 0x6b04
movl $0x1, %r12d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x6535
testl %eax, %eax
jne 0x6a5e
leaq 0x6798(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x2674
jmp 0x6a4e
leaq 0x677d(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x2696
jmp 0x6a4e
callq 0x2040
cmpl $0xb, (%rax)
jne 0x6b5f
movl $0x1, %r12d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x6535
testl %eax, %eax
jne 0x6a5e
leaq 0x673d(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x2630
jmp 0x6a4e
leaq 0x6722(%rip), %rax      # 0xd288
cmpl $0x0, 0x18(%rax)
jle 0x6a4e
callq 0x2652
jmp 0x6a4e
movq 0x6477(%rip), %rax      # 0xcff8
movq (%rax), %rdi
leaq 0x1e13(%rip), %rsi      # 0x899e
xorl %eax, %eax
callq 0x2260
jmp 0x6a4e
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq