// File: /workspace/github_c_makefile_star2_O2/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 $0xa8, %rsp
movq %rdx, 0x60(%rsp)
movl (%rdx), %eax
leaq 0x983(%rip), %rdx       # 0x3322
leaq 0x30(%rsp), %r15
movq %rdx, (%r15)
leaq 0x9c6(%rip), %r9        # 0x3374
movq %r9, 0x8(%r15)
movq %rsi, 0x10(%r15)
movl %eax, 0x18(%r15)
andl $0x0, 0x1c(%r15)
andq $0x0, 0x20(%r15)
leaq 0x8(%rsp), %r12
movq %rdx, (%r12)
movq %r9, 0x8(%r12)
movq %rcx, 0x10(%r12)
movl %r8d, 0x18(%r12)
andl $0x0, 0x1c(%r12)
andq $0x0, 0x20(%r12)
movq %rdi, %r14
leaq 0x1bb(%rdi), %r13
leaq 0xa(%rdi), %rbx
movq %r13, 0x58(%rsp)
movzbl (%r13), %edx
cmpq $0xff, %rdx
je 0x2a7b
movl 0x48(%rsp), %eax
movl 0x4c(%rsp), %ecx
cmpl %eax, %ecx
je 0x2c3c
imulq $0x48, %rdx, %r13
addq %rbx, %r13
movzbl 0x5(%r13), %esi
movzbl 0x4(%r13), %edx
cmpb %dl, %sil
jae 0x2a55
leaq (%rsi,%r13), %rdi
addq $0x8, %rdi
subq %rsi, %rdx
movq 0x40(%rsp), %rsi
movq %rcx, %r8
shlq $0x4, %r8
movq %rdi, (%rsi,%r8)
incl %ecx
movl %ecx, 0x4c(%rsp)
movq %rdx, 0x8(%rsi,%r8)
cmpl %eax, %ecx
je 0x2c44
movzwl (%r13), %edx
movzwl 0x2(%r13), %eax
subq %rax, %rdx
movq %r15, %rdi
movq %r12, %rsi
callq 0x2c5d
addq $0x6, %r13
jmp 0x29fb
movl 0x4c(%rsp), %eax
cmpl 0x48(%rsp), %eax
je 0x2c44
movl 0x24(%rsp), %ecx
cmpl 0x20(%rsp), %ecx
je 0x2c44
leaq 0x70(%rsp), %r13
leaq 0x8(%rsp), %rbp
cmpb $-0x1, 0x1ba(%r14)
je 0x2c40
movl 0x24(%rsp), %eax
cmpl 0x20(%rsp), %eax
je 0x2c40
movq %r15, 0x68(%rsp)
movzwl 0x8(%r14), %r15d
movups 0x8(%rsp), %xmm0
movups 0x18(%rsp), %xmm1
movaps %xmm0, 0x80(%rsp)
movaps %xmm1, 0x90(%rsp)
movq 0x28(%rsp), %rax
movq %rax, 0xa0(%rsp)
testl %r15d, %r15d
je 0x2b46
movl 0x24(%rsp), %eax
cmpl 0x20(%rsp), %eax
je 0x2b46
movl %r15d, %edx
movq %r13, %rdi
movq %rbp, %rsi
callq 0x2cd9
cmpb $0x0, 0x1bd(%r14)
movq (%r14), %rdi
movq 0x70(%rsp), %rdx
movq 0x78(%rsp), %r12
je 0x2b2f
movq %rdx, %rsi
movq %r12, %rcx
callq 0x2346
jmp 0x2b41
addq $0x1fc, %rdi            # imm = 0x1FC
movq %rdx, %rsi
movq %r12, %rcx
callq 0x2222
subl %r12d, %r15d
jmp 0x2aee
movzbl 0x1ba(%r14), %eax
imulq $0x48, %rax, %rbp
movb 0x6(%rbx,%rbp), %cl
movb %cl, 0x1ba(%r14)
movzbl 0x1bc(%r14), %ecx
cmpq $0xff, %rcx
je 0x2b78
imulq $0x48, %rcx, %rcx
movb %al, 0x6(%rbx,%rcx)
jmp 0x2b7f
movq 0x58(%rsp), %rcx
movb %al, (%rcx)
addq %rbx, %rbp
movb %al, 0x1bc(%r14)
movl 0x8(%r14), %r13d
subl %r15d, %r13d
movw %r13w, (%rbp)
movw $0xff00, 0x5(%rbp)      # imm = 0xFF00
andw $0x0, 0x2(%rbp)
cmpb $0x0, 0x1bd(%r14)
je 0x2bd4
movq (%r14), %rax
cmpb $0x0, 0x195(%rax)
movq 0x68(%rsp), %r15
je 0x2bd7
cmpl $0x1, 0x190(%rax)
jne 0x2bd4
movl $0x2, 0x190(%rax)
pushq $0x2
popq %r15
jmp 0x2bd7
xorl %r15d, %r15d
leaq 0x8(%rbp), %r12
movq %r12, %rdi
xorl %esi, %esi
movq %r15, %rdx
callq 0x1080
movb %r15b, 0x4(%rbp)
movl 0x48(%rsp), %eax
movl 0x4c(%rsp), %ecx
cmpl %eax, %ecx
je 0x2c13
movq 0x40(%rsp), %rdx
movq %rcx, %rsi
shlq $0x4, %rsi
movq %r12, (%rdx,%rsi)
incl %ecx
movl %ecx, 0x4c(%rsp)
movq %r15, 0x8(%rdx,%rsi)
leaq 0x8(%rsp), %rbp
cmpl %eax, %ecx
je 0x2c32
movzwl %r13w, %edx
leaq 0x30(%rsp), %rdi
leaq 0x80(%rsp), %rsi
callq 0x2c5d
leaq 0x70(%rsp), %r13
jmp 0x2aa1
movl %ecx, %eax
jmp 0x2c44
movl 0x4c(%rsp), %eax
movq 0x60(%rsp), %rcx
movl %eax, (%rcx)
addq $0xa8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq