// File: king1600[P]cordpp/src/ws.cc
// Function: cordpp::WebsockClient::send(char const*, unsigned long, cordpp::WebsockOp)
void WebsockClient::send(const char *data, const size_t len, WebsockOp op) {
  // check if allowed to send data
  if (state != WebsockState::open || !connection.is_connected())
    return;
  
  // calculate payload size padding
  uint8_t padding;
  if (len < 0x7e)
    padding = 0;
  else if (len < 0x10000)
    padding = 2;
  else
    padding = 8;

  // create output buffer and incrementer
  uint64_t i, offset = 0;
  uint8_t output[6 + len + padding];

  // add the first byte header
  output[offset++] = 0x80 | static_cast<uint8_t>(op);

  // add the payload length
  if (padding == 0) {
    output[offset++] = 0x80 | len;
  } else if (padding == 2) {
    output[offset++] = 0x80 | 0x7e;
    output[offset++] = (len >> 8) & 0xff;
    output[offset++] = len & 0xff;
  } else if (padding == 8) {
    output[offset++] = 0x80 | 0x7f;
    output[offset++] = (len >> 56) & 0xff;
    output[offset++] = (len >> 48) & 0xff;
    output[offset++] = (len >> 40) & 0xff;
    output[offset++] = (len >> 32) & 0xff;
    output[offset++] = (len >> 24) & 0xff;
    output[offset++] = (len >> 16) & 0xff;
    output[offset++] = (len >> 8) & 0xff;
    output[offset++] = len & 0xff;
  }

  // add the mask and get its offset
  uint8_t mask_offset = offset;
  output[offset++] = rand_byte();
  output[offset++] = rand_byte();
  output[offset++] = rand_byte();
  output[offset++] = rand_byte();

  // add payload data and mask it
  for (i = 0; i < len; i++)
    output[offset++] = static_cast<uint8_t>(data[i])
      ^ output[(i % 4) + mask_offset];

  // write data to connection
  connection.write(reinterpret_cast<const char*>(output), sizeof(output));
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x50(%rbp)
cmpl $0x0, 0x398(%rax)
jne 0x89099
movq -0x50(%rbp), %rdi
addq $0x40, %rdi
callq 0x5a7b0
testb $0x1, %al
jne 0x8909e
jmp 0x893e1
cmpq $0x7e, -0x18(%rbp)
jae 0x890ab
movb $0x0, -0x1d(%rbp)
jmp 0x890c1
cmpq $0x10000, -0x18(%rbp)   # imm = 0x10000
jae 0x890bb
movb $0x2, -0x1d(%rbp)
jmp 0x890bf
movb $0x8, -0x1d(%rbp)
jmp 0x890c1
movq $0x0, -0x30(%rbp)
movq -0x18(%rbp), %rax
movzbl -0x1d(%rbp), %ecx
movl %ecx, %edx
leaq 0x6(%rax,%rdx), %rcx
movq %rcx, -0x60(%rbp)
movq %rsp, %rsi
movq %rsi, -0x38(%rbp)
leaq 0x15(%rax,%rdx), %rdx
andq $-0x10, %rdx
movq %rsp, %rax
subq %rdx, %rax
movq %rax, -0x58(%rbp)
movq %rax, %rsp
movq %rcx, -0x40(%rbp)
movl -0x1c(%rbp), %ecx
movzbl %cl, %ecx
orl $0x80, %ecx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movzbl -0x1d(%rbp), %eax
cmpl $0x0, %eax
jne 0x8914e
movq -0x58(%rbp), %rax
movq -0x18(%rbp), %rcx
orq $0x80, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
jmp 0x892f1
movzbl -0x1d(%rbp), %eax
cmpl $0x2, %eax
jne 0x891b5
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb $-0x2, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x8, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
jmp 0x892ef
movzbl -0x1d(%rbp), %eax
cmpl $0x8, %eax
jne 0x892ed
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rdx
addq $0x1, %rdx
movq %rdx, -0x30(%rbp)
movb $-0x1, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x38, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x30, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x28, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x20, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x18, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x10, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
shrq $0x8, %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x18(%rbp), %rcx
andq $0xff, %rcx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
jmp 0x892ef
jmp 0x892f1
movq -0x30(%rbp), %rax
movb %al, -0x41(%rbp)
callq 0x896c0
movb %al, %dl
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
callq 0x896c0
movb %al, %dl
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
callq 0x896c0
movb %al, %dl
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
callq 0x896c0
movb %al, %dl
movq -0x58(%rbp), %rax
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq $0x0, -0x28(%rbp)
movq -0x28(%rbp), %rax
cmpq -0x18(%rbp), %rax
jae 0x893c5
movq -0x58(%rbp), %rax
movq -0x10(%rbp), %rcx
movq -0x28(%rbp), %rdx
movzbl (%rcx,%rdx), %ecx
movq -0x28(%rbp), %rdx
andq $0x3, %rdx
movzbl -0x41(%rbp), %esi
addq %rsi, %rdx
movzbl (%rax,%rdx), %edx
xorl %edx, %ecx
movb %cl, %dl
movq -0x30(%rbp), %rcx
movq %rcx, %rsi
addq $0x1, %rsi
movq %rsi, -0x30(%rbp)
movb %dl, (%rax,%rcx)
movq -0x28(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x28(%rbp)
jmp 0x89374
movq -0x60(%rbp), %rdx
movq -0x58(%rbp), %rsi
movq -0x50(%rbp), %rdi
addq $0x40, %rdi
callq 0x5a7d0
movq -0x38(%rbp), %rax
movq %rax, %rsp
movq %rbp, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)