// File: /workspace/github_c_makefile_star2_O1/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 %rdi, %r14
movq %rdx, 0x68(%rsp)
movl (%rdx), %eax
leaq 0x97a(%rip), %rdx       # 0x36ec
movq %rdx, (%rsp)
leaq 0x9c6(%rip), %rdi       # 0x3743
movq %rdi, 0x8(%rsp)
movq %rsi, 0x10(%rsp)
movl %eax, 0x18(%rsp)
xorl %eax, %eax
movl %eax, 0x1c(%rsp)
movq %rax, 0x20(%rsp)
movq %rdx, 0x28(%rsp)
movq %rdi, 0x30(%rsp)
movq %rcx, 0x38(%rsp)
movl %r8d, 0x40(%rsp)
movl %eax, 0x44(%rsp)
movq %rax, 0x48(%rsp)
movb 0x1bb(%r14), %dl
cmpb $-0x1, %dl
je 0x2e4a
leaq 0xa(%r14), %rbx
movq %rsp, %r15
leaq 0x28(%rsp), %r12
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %eax, %ecx
je 0x3048
movzbl %dl, %edx
leaq (%rdx,%rdx,8), %rdx
leaq (%rbx,%rdx,8), %r13
movzbl 0x5(%r13), %esi
movzbl 0x4(%r13), %edx
cmpb %dl, %sil
jae 0x2e1f
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, 0x1c(%rsp)
je 0x3048
movzwl (%r13), %edx
movzwl 0x2(%r13), %eax
subq %rax, %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x3065
movb 0x6(%r13), %dl
cmpb $-0x1, %dl
jne 0x2dcf
movl 0x1c(%rsp), %eax
cmpl 0x18(%rsp), %eax
je 0x3048
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x3048
cmpb $-0x1, 0x1ba(%r14)
je 0x3048
leaq 0xa(%r14), %r15
leaq 0x28(%rsp), %rbp
movq %r15, 0x60(%rsp)
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x3048
movzwl 0x8(%r14), %ebx
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 %ebx, %ebx
je 0x2f50
movl 0x44(%rsp), %eax
cmpl 0x40(%rsp), %eax
je 0x2f50
movl %ebx, %edx
leaq 0x50(%rsp), %rdi
movq %rbp, %rsi
callq 0x30e3
cmpb $0x0, 0x1bd(%r14)
movq (%r14), %r12
movq 0x50(%rsp), %rdx
je 0x2f2f
movq 0x58(%rsp), %rcx
leaq 0x7c(%r12), %rdi
movq %rdx, %rsi
callq 0x254f
cmpb $0x0, 0x195(%r12)
jne 0x2f24
cmpl $0x2, 0x190(%r12)
jne 0x2f24
movl $0x3, 0x190(%r12)
movb $0x1, 0x195(%r12)
jmp 0x2f46
movq 0x58(%rsp), %rcx
addq $0x1fc, %r12            # imm = 0x1FC
movq %r12, %rdi
movq %rdx, %rsi
callq 0x254f
subl 0x58(%rsp), %ebx
jne 0x2ec1
movzbl 0x1ba(%r14), %eax
leaq (%rax,%rax,8), %rcx
movb 0x6(%r15,%rcx,8), %dl
movb %dl, 0x1ba(%r14)
movzbl 0x1bc(%r14), %edx
cmpq $0xff, %rdx
je 0x2f84
leaq (%rdx,%rdx,8), %rdx
movb %al, 0x6(%r15,%rdx,8)
jmp 0x2f8b
movb %al, 0x1bb(%r14)
leaq (%r15,%rcx,8), %r15
movb %al, 0x1bc(%r14)
movl 0x8(%r14), %eax
subl %ebx, %eax
movw %ax, (%r15)
movw $0xff00, 0x5(%r15)      # imm = 0xFF00
movw $0x0, 0x2(%r15)
cmpb $0x0, 0x1bd(%r14)
je 0x2fdf
movq (%r14), %rax
cmpb $0x0, 0x195(%rax)
je 0x2fe2
cmpl $0x1, 0x190(%rax)
jne 0x2fdf
movl $0x2, 0x190(%rax)
movl $0x2, %r13d
jmp 0x2fe2
xorl %r13d, %r13d
leaq 0x8(%r15), %r12
movq %r12, %rdi
xorl %esi, %esi
movq %r13, %rdx
callq 0x1080
movb %r13b, 0x4(%r15)
movl 0x18(%rsp), %eax
movl 0x1c(%rsp), %ecx
cmpl %eax, %ecx
je 0x301e
movq 0x10(%rsp), %rdx
movq %rcx, %rsi
shlq $0x4, %rsi
movq %r12, (%rdx,%rsi)
incl %ecx
movl %ecx, 0x1c(%rsp)
movq %r13, 0x8(%rdx,%rsi)
cmpl %eax, 0x1c(%rsp)
je 0x3035
movzwl (%r15), %edx
movq %rsp, %rdi
leaq 0x70(%rsp), %rsi
callq 0x3065
cmpb $-0x1, 0x1ba(%r14)
movq 0x60(%rsp), %r15
jne 0x2e82
movl 0x1c(%rsp), %eax
movq 0x68(%rsp), %rcx
movl %eax, (%rcx)
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq