// File: /workspace/github_c_makefile_star2_O3/agl[P]obstcp/libobstcp.c
// Function: obstcp_accum_prepare
void EXPORTED
obstcp_accum_prepare(struct obstcp_accum *ac,
                     struct iovec *out, unsigned *onumout,
                     const struct iovec *in, unsigned numin) {
  const unsigned numout = *onumout;
  struct iovec_cursor outc, inc, inccopy;
  struct obstcp_accum_buffer *ab = NULL;
  uint8_t c;

  iovec_cursor_init(&outc, out, numout);
  iovec_cursor_init(&inc, (struct iovec *) in, numin);

  // walk the list of buffers and add them to the output list
  for (c = ac->data_head; c != 0xff; c = ab->next) {
    ab = &ac->buffers[c];

    if (iovec_cursor_full(&outc)) goto out;
    if (ab->prefix_used < ab->prefix_len) {
      iovec_cursor_append(&outc,
                          ab->prefix + ab->prefix_used,
                          ab->prefix_len - ab->prefix_used);
    }

    if (iovec_cursor_full(&outc)) goto out;
    iovec_cursor_copy(&outc, &inc, ab->payload_len - ab->payload_used);
  }

  if (iovec_cursor_full(&outc) || iovec_cursor_full(&inc)) goto out;

  // If there are buffers remaining and data still in the input, we might as
  // well encrypt some more.
  while (ac->free_head != 0xff && !iovec_cursor_full(&inc)) {
    unsigned frame_remaining = ac->frame_size;
    struct iovec iov, iniov;

    // save the current cursor so that we can copy from it later
    memcpy(&inccopy, &inc, sizeof(inc));

    // try to fill up a whole frame
    while (frame_remaining && !iovec_cursor_full(&inc)) {
      iovec_cursor_get(&iov, &inc, frame_remaining);
      if (ac->is_server) {
        obstcp_server_encrypt((struct obstcp_server_ctx *) ac->ctx,
                              iov.iov_base, iov.iov_base, iov.iov_len);
      } else {
        obstcp_client_encrypt((struct obstcp_client_ctx *) ac->ctx,
                              iov.iov_base, iov.iov_base, iov.iov_len);
      }
      frame_remaining -= iov.iov_len;
    }

    // pop a buffer from the free list
    const uint8_t buffer_num = ac->free_head;
    ab = &ac->buffers[ac->free_head];
    ac->free_head = ab->next;

    if (ac->data_tail != 0xff) {
      ac->buffers[ac->data_tail].next = buffer_num;
    } else {
      ac->data_head = buffer_num;
    }
    ac->data_tail = buffer_num;

    ab->payload_len = ac->frame_size - frame_remaining;
    ab->payload_used = ab->prefix_used = 0;
    ab->next = 0xff;

    if (ac->is_server) {
      obstcp_server_prefix((struct obstcp_server_ctx *) ac->ctx, &iniov);
    } else {
      obstcp_client_prefix((struct obstcp_client_ctx *) ac->ctx, &iniov);
    }

    assert(iniov.iov_len < OBSTCP_MAX_PREFIX);
    memcpy(ab->prefix, iniov.iov_base, iniov.iov_len);
    ab->prefix_len = iniov.iov_len;

    if (!iovec_cursor_full(&outc)) {
      iovec_cursor_append(&outc, ab->prefix, ab->prefix_len);
    }
    if (!iovec_cursor_full(&outc)) {
      iovec_cursor_copy(&outc, &inccopy, ab->payload_len);
    }
  }

 out:
  *onumout = outc.i;
  return;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rdx, %rbp
movq %rdi, %r14
movl (%rdx), %edx
leaq 0x9a1(%rip), %rdi       # 0x3571
movq %rdi, (%rsp)
leaq 0x9ed(%rip), %r9        # 0x35c8
movq %r9, 0x8(%rsp)
movq %rsi, 0x10(%rsp)
movl %edx, 0x18(%rsp)
xorl %eax, %eax
movl %eax, 0x1c(%rsp)
movq %rax, 0x20(%rsp)
movq %rdi, 0x28(%rsp)
movq %r9, 0x30(%rsp)
movq %rcx, 0x38(%rsp)
movl %r8d, 0x40(%rsp)
movl %eax, 0x44(%rsp)
movq %rax, 0x48(%rsp)
movb 0x1bb(%r14), %sil
cmpb $-0x1, %sil
je 0x2cb1
leaq 0xa(%r14), %rbx
movq %rsp, %r15
leaq 0x28(%rsp), %r12
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %eax, %ecx
je 0x2eb6
movzbl %sil, %edx
leaq (%rdx,%rdx,8), %rdx
leaq (%rbx,%rdx,8), %r13
movzbl 0x5(%r13), %esi
movzbl 0x4(%r13), %edx
cmpb %dl, %sil
jae 0x2c7f
leaq (%rsi,%r13), %rdi
addq $0x8, %rdi
subq %rsi, %rdx
movq 0x10(%rsp), %rsi
movq %rcx, %r8
shlq $0x4, %r8
movq %rdi, (%rsi,%r8)
incl %ecx
movl %ecx, 0x1c(%rsp)
movq %rdx, 0x8(%rsi,%r8)
cmpl %eax, %ecx
je 0x2eb6
movzwl (%r13), %edx
movzwl 0x2(%r13), %eax
subq %rax, %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x2ecb
movb 0x6(%r13), %sil
cmpb $-0x1, %sil
jne 0x2c2e
movl 0x18(%rsp), %edx
movl 0x1c(%rsp), %eax
cmpl %edx, %eax
je 0x2eb6
movl 0x44(%rsp), %ecx
cmpl 0x40(%rsp), %ecx
je 0x2eb6
movb 0x1ba(%r14), %cl
cmpb $-0x1, %cl
je 0x2eb6
movq %rbp, 0x50(%rsp)
leaq 0xa(%r14), %r13
movq %r13, 0x58(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x2ead
movzwl 0x8(%r14), %r15d
movups 0x28(%rsp), %xmm0
movups 0x38(%rsp), %xmm1
movaps %xmm0, 0x70(%rsp)
movaps %xmm1, 0x80(%rsp)
movq 0x48(%rsp), %rax
movq %rax, 0x90(%rsp)
testl %r15d, %r15d
je 0x2db6
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x2dad
movl %r15d, %edx
leaq 0x60(%rsp), %rdi
leaq 0x28(%rsp), %rsi
callq 0x2f5b
cmpb $0x0, 0x1bd(%r14)
movq (%r14), %rbx
movq 0x60(%rsp), %rdx
movq 0x68(%rsp), %r12
je 0x2d8c
leaq 0x7c(%rbx), %rdi
movq %rdx, %rsi
movq %r12, %rcx
callq 0x230a
cmpb $0x0, 0x195(%rbx)
jne 0x2d83
cmpl $0x2, 0x190(%rbx)
jne 0x2d83
movl $0x3, 0x190(%rbx)
movb $0x1, 0x195(%rbx)
jmp 0x2da1
addq $0x1fc, %rbx            # imm = 0x1FC
movq %rbx, %rdi
movq %rdx, %rsi
movq %r12, %rcx
callq 0x230a
subl %r12d, %r15d
jne 0x2d25
xorl %r15d, %r15d
movb 0x1ba(%r14), %cl
jmp 0x2db9
xorl %r15d, %r15d
movzbl %cl, %eax
leaq (%rax,%rax,8), %rax
movb 0x6(%r13,%rax,8), %dl
movb %dl, 0x1ba(%r14)
movzbl 0x1bc(%r14), %edx
cmpq $0xff, %rdx
je 0x2de8
leaq (%rdx,%rdx,8), %rdx
movb %cl, 0x6(%r13,%rdx,8)
jmp 0x2def
movb %cl, 0x1bb(%r14)
leaq (%r13,%rax,8), %r13
movb %cl, 0x1bc(%r14)
movl 0x8(%r14), %r12d
subl %r15d, %r12d
movw %r12w, (%r13)
movw $0xff00, 0x5(%r13)      # imm = 0xFF00
movw $0x0, 0x2(%r13)
cmpb $0x0, 0x1bd(%r14)
je 0x2e45
movq (%r14), %rax
cmpb $0x0, 0x195(%rax)
je 0x2e47
cmpl $0x1, 0x190(%rax)
jne 0x2e45
movl $0x2, 0x190(%rax)
movl $0x2, %ebp
jmp 0x2e47
xorl %ebp, %ebp
leaq 0x8(%r13), %rbx
movq %rbx, %rdi
xorl %esi, %esi
movq %rbp, %rdx
callq 0x1080
movb %bpl, 0x4(%r13)
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %eax, %ecx
je 0x2e98
movq 0x10(%rsp), %rdx
movq %rcx, %rsi
shlq $0x4, %rsi
movq %rbx, (%rdx,%rsi)
incl %ecx
movl %ecx, 0x1c(%rsp)
movq %rbp, 0x8(%rdx,%rsi)
cmpl %eax, %ecx
je 0x2e98
movzwl %r12w, %edx
movq %rsp, %rdi
leaq 0x70(%rsp), %rsi
callq 0x2ecb
movb 0x1ba(%r14), %cl
cmpb $-0x1, %cl
movq 0x58(%rsp), %r13
jne 0x2ce5
movl 0x1c(%rsp), %eax
movq 0x50(%rsp), %rbp
movl %eax, (%rbp)
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq