// File: /workspace/github_c_makefile_star2_O0/TimeToogo[P]ff-proxy/src/parser.c
// Function: ff_request_parse_data_chunk
void ff_request_parse_data_chunk(struct ff_request *request, uint32_t buff_size, void *buff)
{
    size_t i = 0;

    if (buff_size < sizeof(struct __raw_ff_request_header))
    {
        ff_log(FF_WARNING, "Packet buffer to small to contain header (%d)", buff_size);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    struct __raw_ff_request_header *header = (struct __raw_ff_request_header *)buff;
    i += sizeof(struct __raw_ff_request_header);

    // Normalise endianess
    uint16_t version = ntohs(header->version);
    uint64_t request_id = ntohll(header->request_id);
    uint32_t total_length = ntohl(header->total_length);
    uint32_t chunk_offset = ntohl(header->chunk_offset);
    uint16_t chunk_length = ntohs(header->chunk_length);

    if (request->version != FF_VERSION_1)
    {
        ff_log(FF_WARNING, "Request received with unknown version flag %d", request->version);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    if (version != request->version)
    {
        ff_log(FF_WARNING, "Mismatch between request version (%d) and chunk version (%d)", request->version, version);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    if (request_id != request->request_id)
    {
        ff_log(FF_WARNING, "Mismatch between request ID (%d) and chunk ID (%d)", request->request_id, request_id);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    if (total_length != request->payload_length)
    {
        ff_log(FF_WARNING, "Mismatch between request length (%d) and chunk length (%d)", request->payload_length, total_length);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    if (chunk_offset + chunk_length > request->payload_length)
    {
        ff_log(FF_WARNING, "Chunk offset and length too long");
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    if (buff_size < i + sizeof(struct __raw_ff_request_option_header))
    {
        ff_log(FF_WARNING, "Packet buffer ran out while looking for TLV options");
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    // Only first request can contain options
    if (header->chunk_offset == 0)
    {
        size_t options_i = ff_request_parse_options(request, buff_size - i, buff + i);

        if (options_i == 0)
        {
            request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
            return;
        }

        i += options_i;
    }
    else
    {
        struct __raw_ff_request_option_header *option_header = (struct __raw_ff_request_option_header *)(buff + i);

        i += sizeof(struct __raw_ff_request_option_header);

        if (option_header->type != FF_REQUEST_OPTION_TYPE_EOL)
        {
            ff_log(FF_WARNING, "Noninitial packets cannot contain request options");
            request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
            return;
        }
    }

    if (buff_size < i + chunk_length)
    {
        ff_log(FF_WARNING, "Packet buffer ran out while receiving payload. Expected %hu bytes, %u bytes remain", chunk_length, buff_size - i);
        request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
        return;
    }

    struct ff_request_payload_node *node = ff_request_payload_node_alloc();
    node->offset = chunk_offset;
    node->length = chunk_length;

    ff_request_payload_load_buff(
        node,
        buff_size - i,
        buff + i);

    if (request->payload == NULL)
    {
        request->payload = node;
        request->received_length = node->length;
    }
    else
    {
        struct ff_request_payload_node *current_node = request->payload;

        while (1)
        {

            bool overlaps_existing_node = node->offset < current_node->offset + current_node->length && current_node->offset <= node->offset + node->length;
            if (overlaps_existing_node)
            {
                ff_log(FF_WARNING,
                       "Received chunk range overlaps existing data. Received byte range [%u, %u] intersects existing range [%u, %u]",
                       node->offset, node->offset + node->length,
                       current_node->offset, current_node->offset + current_node->length);
                request->state = FF_REQUEST_STATE_RECEIVING_FAIL;
                return;
            }

            if (current_node == NULL || current_node->next == NULL)
            {
                break;
            }

            current_node = current_node->next;
        }

        current_node->next = node;
        request->received_length += node->length;
    }

    if (request->received_length == request->payload_length)
    {
        ff_log(FF_DEBUG, "Request %lu successfully received", request->request_id);
        request->state = FF_REQUEST_STATE_RECEIVED;
    }
    else
    {
        ff_log(FF_DEBUG, "Finished parsing request %lu partial packet, %lu bytes remain", request->request_id, request->payload_length - request->received_length);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x90, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movq $0x0, -0x20(%rbp)
movl -0xc(%rbp), %eax
cmpq $0x14, %rax
jae 0x51cc
movl -0xc(%rbp), %edx
movl $0x3, %edi
leaq 0x2bc4(%rip), %rsi      # 0x7d7a
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movq -0x18(%rbp), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
addq $0x14, %rax
movq %rax, -0x20(%rbp)
movq -0x28(%rbp), %rax
movzwl (%rax), %edi
callq 0x24d0
movw %ax, -0x2a(%rbp)
movl $0x1, %edi
callq 0x23a0
movl %eax, %ecx
movl $0x1, %eax
cmpl %ecx, %eax
jne 0x5213
movq -0x28(%rbp), %rax
movq 0x2(%rax), %rax
movq %rax, -0x78(%rbp)
jmp 0x5258
movq -0x28(%rbp), %rcx
movabsq $0xffffffff, %rax       # imm = 0xFFFFFFFF
andq 0x2(%rcx), %rax
movl %eax, %edi
callq 0x23a0
movl %eax, %eax
shlq $0x20, %rax
movq %rax, -0x80(%rbp)
movq -0x28(%rbp), %rax
movq 0x2(%rax), %rax
shrq $0x20, %rax
movl %eax, %edi
callq 0x23a0
movl %eax, %ecx
movq -0x80(%rbp), %rax
movl %ecx, %ecx
orq %rcx, %rax
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x28(%rbp), %rax
movl 0xa(%rax), %edi
callq 0x23a0
movl %eax, -0x3c(%rbp)
movq -0x28(%rbp), %rax
movl 0xe(%rax), %edi
callq 0x23a0
movl %eax, -0x40(%rbp)
movq -0x28(%rbp), %rax
movzwl 0x12(%rax), %edi
callq 0x24d0
movw %ax, -0x42(%rbp)
movq -0x8(%rbp), %rax
cmpl $0x1, 0x4(%rax)
je 0x52c2
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edx
movl $0x3, %edi
leaq 0x2afc(%rip), %rsi      # 0x7da8
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movzwl -0x2a(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpl 0x4(%rcx), %eax
je 0x52fc
movq -0x8(%rbp), %rax
movl 0x4(%rax), %edx
movzwl -0x2a(%rbp), %ecx
movl $0x3, %edi
leaq 0x2af0(%rip), %rsi      # 0x7dd6
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movq -0x38(%rbp), %rax
movq -0x8(%rbp), %rcx
cmpq 0x20(%rcx), %rax
je 0x5338
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdx
movq -0x38(%rbp), %rcx
movl $0x3, %edi
leaq 0x2af1(%rip), %rsi      # 0x7e13
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movl -0x3c(%rbp), %eax
movq -0x8(%rbp), %rcx
cmpq 0x40(%rcx), %rax
je 0x5372
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rdx
movl -0x3c(%rbp), %ecx
movl $0x3, %edi
leaq 0x2aea(%rip), %rsi      # 0x7e46
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movl -0x40(%rbp), %eax
movzwl -0x42(%rbp), %ecx
addl %ecx, %eax
movl %eax, %eax
movq -0x8(%rbp), %rcx
cmpq 0x40(%rcx), %rax
jbe 0x53a9
movl $0x3, %edi
leaq 0x2aee(%rip), %rsi      # 0x7e81
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movl -0xc(%rbp), %eax
movq -0x20(%rbp), %rcx
addq $0x3, %rcx
cmpq %rcx, %rax
jae 0x53db
movl $0x3, %edi
leaq 0x2add(%rip), %rsi      # 0x7ea2
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movq -0x28(%rbp), %rax
cmpl $0x0, 0xe(%rax)
jne 0x5427
movq -0x8(%rbp), %rdi
movl -0xc(%rbp), %eax
subq -0x20(%rbp), %rax
movl %eax, %esi
movq -0x18(%rbp), %rdx
addq -0x20(%rbp), %rdx
callq 0x58c0
movq %rax, -0x50(%rbp)
cmpq $0x0, -0x50(%rbp)
jne 0x5419
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
movq -0x50(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x20(%rbp)
jmp 0x546f
movq -0x18(%rbp), %rax
addq -0x20(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x20(%rbp), %rax
addq $0x3, %rax
movq %rax, -0x20(%rbp)
movq -0x58(%rbp), %rax
movzbl (%rax), %eax
cmpl $0x0, %eax
je 0x546d
movl $0x3, %edi
leaq 0x2a7f(%rip), %rsi      # 0x7ed6
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
jmp 0x546f
movl -0xc(%rbp), %eax
movq -0x20(%rbp), %rcx
movzwl -0x42(%rbp), %edx
addq %rdx, %rcx
cmpq %rcx, %rax
jae 0x54b1
movzwl -0x42(%rbp), %edx
movl -0xc(%rbp), %eax
movl %eax, %ecx
subq -0x20(%rbp), %rcx
movl $0x3, %edi
leaq 0x2a6d(%rip), %rsi      # 0x7f08
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
callq 0x5ea0
movq %rax, -0x60(%rbp)
movl -0x40(%rbp), %eax
movw %ax, %cx
movq -0x60(%rbp), %rax
movw %cx, (%rax)
movw -0x42(%rbp), %cx
movq -0x60(%rbp), %rax
movw %cx, 0x2(%rax)
movq -0x60(%rbp), %rdi
movl -0xc(%rbp), %eax
subq -0x20(%rbp), %rax
movl %eax, %esi
movq -0x18(%rbp), %rdx
addq -0x20(%rbp), %rdx
callq 0x5ef0
movq -0x8(%rbp), %rax
cmpq $0x0, 0x50(%rax)
jne 0x551b
movq -0x60(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x50(%rax)
movq -0x60(%rbp), %rax
movzwl 0x2(%rax), %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
movq %rcx, 0x48(%rax)
jmp 0x561b
movq -0x8(%rbp), %rax
movq 0x50(%rax), %rax
movq %rax, -0x68(%rbp)
movq -0x60(%rbp), %rax
movzwl (%rax), %ecx
movq -0x68(%rbp), %rax
movzwl (%rax), %edx
movq -0x68(%rbp), %rax
movzwl 0x2(%rax), %eax
addl %eax, %edx
xorl %eax, %eax
cmpl %edx, %ecx
movb %al, -0x81(%rbp)
jge 0x556e
movq -0x68(%rbp), %rax
movzwl (%rax), %eax
movq -0x60(%rbp), %rcx
movzwl (%rcx), %ecx
movq -0x60(%rbp), %rdx
movzwl 0x2(%rdx), %edx
addl %edx, %ecx
cmpl %ecx, %eax
setle %al
movb %al, -0x81(%rbp)
movb -0x81(%rbp), %al
andb $0x1, %al
movb %al, -0x69(%rbp)
testb $0x1, -0x69(%rbp)
je 0x55d4
movq -0x60(%rbp), %rax
movzwl (%rax), %edx
movq -0x60(%rbp), %rax
movzwl (%rax), %ecx
movq -0x60(%rbp), %rax
movzwl 0x2(%rax), %eax
addl %eax, %ecx
movq -0x68(%rbp), %rax
movzwl (%rax), %r8d
movq -0x68(%rbp), %rax
movzwl (%rax), %r9d
movq -0x68(%rbp), %rax
movzwl 0x2(%rax), %eax
addl %eax, %r9d
movl $0x3, %edi
leaq 0x299d(%rip), %rsi      # 0x7f5b
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x2, (%rax)
jmp 0x567f
cmpq $0x0, -0x68(%rbp)
je 0x55e6
movq -0x68(%rbp), %rax
cmpq $0x0, 0x10(%rax)
jne 0x55e8
jmp 0x55f9
movq -0x68(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x68(%rbp)
jmp 0x5527
movq -0x60(%rbp), %rcx
movq -0x68(%rbp), %rax
movq %rcx, 0x10(%rax)
movq -0x60(%rbp), %rax
movzwl 0x2(%rax), %eax
movl %eax, %ecx
movq -0x8(%rbp), %rax
addq 0x48(%rax), %rcx
movq %rcx, 0x48(%rax)
movq -0x8(%rbp), %rax
movq 0x48(%rax), %rax
movq -0x8(%rbp), %rcx
cmpq 0x40(%rcx), %rax
jne 0x5654
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdx
movl $0x1, %edi
leaq 0x2987(%rip), %rsi      # 0x7fc8
movb $0x0, %al
callq 0x4d70
movq -0x8(%rbp), %rax
movl $0x1, (%rax)
jmp 0x567f
movq -0x8(%rbp), %rax
movq 0x20(%rax), %rdx
movq -0x8(%rbp), %rax
movq 0x40(%rax), %rcx
movq -0x8(%rbp), %rax
subq 0x48(%rax), %rcx
movl $0x1, %edi
leaq 0x2972(%rip), %rsi      # 0x7fea
movb $0x0, %al
callq 0x4d70
addq $0x90, %rsp
popq %rbp
retq
nopl (%rax,%rax)