// File: alfanick[P]rest-cpp/src/rest/request.cpp
// Function: REST::Request::process()
void Request::process() {
  std::string line;
  bool is_header = true;
  char buffer[BUFFER_SIZE];
  ssize_t request_length;

  // receive data from client
  request_length = recv(handle, buffer, BUFFER_SIZE, 0);

  // handle timeout
  if (request_length <= 0)
    throw HTTP::RequestTimeout();

  // parse each line
  std::istringstream request_stream(buffer);

  // first line is HTTP header
  std::getline(request_stream, line);
  parse_header(line);

  // parse headers
  while (std::getline(request_stream, line)) {
    // next lines are headers, strip them
    line.erase(line.find_last_not_of(" \n\r\t")+1);

    // if line is empty, then content should follow
    if (line.size() == 0) {
      is_header = false;
      break;
    }

    // extract name and value from header
    size_t colon;
    std::string name = line.substr(0, colon = line.find(":"));
    std::string value = line.substr(colon+1);
    value.erase(0, value.find_first_not_of(" \n\r\t"));

    headers.emplace(name, value);
  }

  // TODO: handle long headers (longer than buffer)
  // if has content
  if (!is_header) {
    // assume proper content length
    size_t content_length = header("Content-Length", 0);

    // TODO: config
    if (content_length > 1024 * 1024 * 128)
      throw HTTP::PayloadTooLarge();

    if (content_length > 0) {
      raw.reserve(content_length);
      // read whats left in header
      length = std::min(content_length, (size_t)(request_length - request_stream.tellg()));
      raw.append(buffer + request_stream.tellg(), length);

      if (length < content_length) {
        char* large_buffer = new char[content_length];

        // receive some more
        while (length < content_length) {
          memset(large_buffer, 0, content_length);
          ssize_t buffer_length = recv(handle, large_buffer, content_length, 0);

          if (buffer_length <= 0)
            throw HTTP::RequestTimeout();

          raw.append(large_buffer, buffer_length);
          length += buffer_length;
        }

        delete[] large_buffer;
      }
    }
  }

  // if has some content
  if (!raw.empty()) {
    // try to parse it
    std::string ct = header("Content-Type", "");

    if (!ct.empty()) {
      if (ct == "application/x-www-form-urlencoded") {
        parse_query_string(raw);
      } else
      if (ct == "application/json" || ct == "text/json") {
        try {
          data = nlohmann::json::parse(raw);
        } catch (...) {
          throw HTTP::BadRequest();
        }
      }
    }
  }
}

// Assembly:
subq $0x1468, %rsp           # imm = 0x1468
movq %rdi, 0x1460(%rsp)
movq 0x1460(%rsp), %rax
movq %rax, 0x128(%rsp)
leaq 0x1440(%rsp), %rdi
callq 0x959e0
movq 0x128(%rsp), %rax
movb $0x1, 0x143f(%rsp)
movl 0xc8(%rax), %edi
leaq 0x430(%rsp), %rsi
movl $0x1000, %edx           # imm = 0x1000
xorl %ecx, %ecx
callq 0x8eb40
movq %rax, 0x130(%rsp)
jmp 0x99f40
movq 0x130(%rsp), %rax
movq %rax, 0x428(%rsp)
cmpq $0x0, 0x428(%rsp)
jg 0x99fb5
movl $0x8, %edi
callq 0x8f970
movq %rax, %rdi
movq %rdi, 0x120(%rsp)
movq $0x0, (%rdi)
callq 0x8de20
movq 0x120(%rsp), %rdi
movq 0x6bf75(%rip), %rsi     # 0x105f00
movq 0x6c016(%rip), %rdx     # 0x105fa8
callq 0x97c60
jmp 0x9a9ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a9dd
leaq 0x277(%rsp), %rdi
movq %rdi, 0x118(%rsp)
callq 0x98200
movq 0x118(%rsp), %rdx
leaq 0x278(%rsp), %rdi
leaq 0x430(%rsp), %rsi
callq 0x95700
jmp 0x99fe9
leaq 0x298(%rsp), %rdi
leaq 0x278(%rsp), %rsi
movl $0x8, %edx
callq 0x97990
jmp 0x9a005
leaq 0x278(%rsp), %rdi
callq 0x99830
leaq 0x277(%rsp), %rdi
callq 0x938a0
leaq 0x298(%rsp), %rdi
leaq 0x1440(%rsp), %rsi
callq 0x8db70
jmp 0x9a036
movq 0x128(%rsp), %rdi
leaq 0x1440(%rsp), %rsi
callq 0x993d0
jmp 0x9a04d
jmp 0x9a04f
leaq 0x298(%rsp), %rdi
leaq 0x1440(%rsp), %rsi
callq 0x8db70
movq %rax, 0x110(%rsp)
jmp 0x9a06e
movq 0x110(%rsp), %rdi
movq (%rdi), %rax
movq -0x18(%rax), %rax
addq %rax, %rdi
callq 0x94b80
movb %al, 0x10f(%rsp)
jmp 0x9a08e
movb 0x10f(%rsp), %al
testb $0x1, %al
jne 0x9a09e
jmp 0x9a2dd
leaq 0x4a1c5(%rip), %rsi     # 0xe426a
leaq 0x1440(%rsp), %rdi
movq %rdi, 0xf8(%rsp)
movq $-0x1, %rdx
movq %rdx, 0x100(%rsp)
callq 0x98510
movq 0xf8(%rsp), %rdi
movq 0x100(%rsp), %rdx
movq %rax, %rsi
incq %rsi
callq 0x8e070
jmp 0x9a0e6
leaq 0x1440(%rsp), %rdi
callq 0x91060
cmpq $0x0, %rax
jne 0x9a168
movb $0x0, 0x143f(%rsp)
jmp 0x9a2dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a13d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
leaq 0x278(%rsp), %rdi
callq 0x99830
leaq 0x277(%rsp), %rdi
callq 0x938a0
jmp 0x9a9dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a9d0
leaq 0x4cd08(%rip), %rsi     # 0xe6e77
xorl %eax, %eax
movl %eax, %edx
movq %rdx, 0xf0(%rsp)
leaq 0x1440(%rsp), %rdi
movq %rdi, 0xe8(%rsp)
callq 0x995d0
movq 0xe8(%rsp), %rsi
movq 0xf0(%rsp), %rdx
movq %rax, %rcx
movq %rcx, 0x268(%rsp)
leaq 0x248(%rsp), %rdi
callq 0x93510
jmp 0x9a1ba
movq 0x268(%rsp), %rdx
incq %rdx
leaq 0x228(%rsp), %rdi
leaq 0x1440(%rsp), %rsi
movq $-0x1, %rcx
callq 0x93510
jmp 0x9a1e3
leaq 0x4a080(%rip), %rsi     # 0xe426a
xorl %eax, %eax
movl %eax, %edx
movq %rdx, 0xe0(%rsp)
leaq 0x228(%rsp), %rdi
movq %rdi, 0xd8(%rsp)
callq 0x90310
movq 0xd8(%rsp), %rdi
movq 0xe0(%rsp), %rsi
movq %rax, %rdx
callq 0x8e070
jmp 0x9a225
movq 0x128(%rsp), %rdi
addq $0x28, %rdi
leaq 0x248(%rsp), %rsi
leaq 0x228(%rsp), %rdx
callq 0x8d7c0
movb %dl, 0xcf(%rsp)
movq %rax, 0xd0(%rsp)
jmp 0x9a257
movb 0xcf(%rsp), %al
movq 0xd0(%rsp), %rcx
movq %rcx, 0x218(%rsp)
movb %al, 0x220(%rsp)
leaq 0x228(%rsp), %rdi
callq 0x99830
leaq 0x248(%rsp), %rdi
callq 0x99830
jmp 0x9a04f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a2cb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
leaq 0x228(%rsp), %rdi
callq 0x99830
leaq 0x248(%rsp), %rdi
callq 0x99830
jmp 0x9a9d0
testb $0x1, 0x143f(%rsp)
jne 0x9a6f7
leaq 0x1ef(%rsp), %rdi
movq %rdi, 0xc0(%rsp)
callq 0x98200
movq 0xc0(%rsp), %rdx
leaq 0x49f60(%rip), %rsi     # 0xe426f
leaq 0x1f0(%rsp), %rdi
callq 0x95700
jmp 0x9a31e
movq 0x128(%rsp), %rdi
movl $0x0, 0x1e8(%rsp)
leaq 0x1f0(%rsp), %rsi
leaq 0x1e8(%rsp), %rdx
callq 0x99700
movl %eax, 0xbc(%rsp)
jmp 0x9a34f
movl 0xbc(%rsp), %eax
cltq
movq %rax, 0xb0(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x99830
leaq 0x1ef(%rsp), %rdi
callq 0x938a0
movq 0xb0(%rsp), %rax
movq %rax, 0x210(%rsp)
cmpq $0x8000000, 0x210(%rsp) # imm = 0x8000000
jbe 0x9a426
movl $0x8, %edi
callq 0x8f970
movq %rax, %rdi
movq %rdi, 0xa8(%rsp)
movq $0x0, (%rdi)
callq 0x99710
movq 0xa8(%rsp), %rdi
movq 0x6b8f4(%rip), %rsi     # 0x105cc0
movq 0x6bb0d(%rip), %rdx     # 0x105ee0
callq 0x97c60
jmp 0x9a9ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a414
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
leaq 0x1f0(%rsp), %rdi
callq 0x99830
leaq 0x1ef(%rsp), %rdi
callq 0x938a0
jmp 0x9a9d0
cmpq $0x0, 0x210(%rsp)
jbe 0x9a6f5
movq 0x128(%rsp), %rdi
addq $0x88, %rdi
movq 0x210(%rsp), %rsi
callq 0x96d70
jmp 0x9a453
movq 0x428(%rsp), %rax
movq %rax, 0x90(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x97df0
movq %rdx, 0x98(%rsp)
movq %rax, 0xa0(%rsp)
jmp 0x9a482
movq 0x98(%rsp), %rax
movq 0xa0(%rsp), %rcx
movq %rcx, 0x1d0(%rsp)
movq %rax, 0x1d8(%rsp)
leaq 0x1d0(%rsp), %rdi
callq 0x90440
movq %rax, 0x88(%rsp)
jmp 0x9a4b9
movq 0x88(%rsp), %rcx
movq 0x90(%rsp), %rax
subq %rcx, %rax
movq %rax, 0x1e0(%rsp)
leaq 0x210(%rsp), %rdi
leaq 0x1e0(%rsp), %rsi
callq 0x91420
movq %rax, 0x80(%rsp)
jmp 0x9a4f3
movq 0x128(%rsp), %rax
movq 0x80(%rsp), %rcx
movq (%rcx), %rcx
movq %rcx, 0xa8(%rax)
addq $0x88, %rax
movq %rax, 0x60(%rsp)
leaq 0x430(%rsp), %rax
movq %rax, 0x68(%rsp)
leaq 0x298(%rsp), %rdi
callq 0x97df0
movq %rdx, 0x70(%rsp)
movq %rax, 0x78(%rsp)
jmp 0x9a53e
movq 0x70(%rsp), %rax
movq 0x78(%rsp), %rcx
movq %rcx, 0x1c0(%rsp)
movq %rax, 0x1c8(%rsp)
leaq 0x1c0(%rsp), %rdi
callq 0x90440
movq %rax, 0x58(%rsp)
jmp 0x9a56c
movq 0x60(%rsp), %rdi
movq 0x128(%rsp), %rax
movq 0x58(%rsp), %rcx
movq 0x68(%rsp), %rsi
addq %rcx, %rsi
movq 0xa8(%rax), %rdx
callq 0x8d7f0
jmp 0x9a594
movq 0x128(%rsp), %rax
movq 0xa8(%rax), %rax
cmpq 0x210(%rsp), %rax
jae 0x9a6f3
movq 0x210(%rsp), %rdi
callq 0x8d0d0
movq %rax, 0x50(%rsp)
jmp 0x9a5c5
movq 0x50(%rsp), %rax
movq %rax, 0x1b8(%rsp)
movq 0x128(%rsp), %rax
movq 0xa8(%rax), %rax
cmpq 0x210(%rsp), %rax
jae 0x9a6d4
movq 0x1b8(%rsp), %rdi
movq 0x210(%rsp), %rdx
xorl %esi, %esi
movl %esi, 0x44(%rsp)
callq 0x8ffc0
movl 0x44(%rsp), %ecx
movq 0x128(%rsp), %rax
movl 0xc8(%rax), %edi
movq 0x1b8(%rsp), %rsi
movq 0x210(%rsp), %rdx
callq 0x8eb40
movq %rax, 0x48(%rsp)
jmp 0x9a638
movq 0x48(%rsp), %rax
movq %rax, 0x1b0(%rsp)
cmpq $0x0, 0x1b0(%rsp)
jg 0x9a68b
movl $0x8, %edi
callq 0x8f970
movq %rax, %rdi
movq %rdi, 0x38(%rsp)
movq $0x0, (%rdi)
callq 0x8de20
movq 0x38(%rsp), %rdi
movq 0x6b886(%rip), %rsi     # 0x105f00
movq 0x6b927(%rip), %rdx     # 0x105fa8
callq 0x97c60
jmp 0x9a9ff
movq 0x128(%rsp), %rdi
addq $0x88, %rdi
movq 0x1b8(%rsp), %rsi
movq 0x1b0(%rsp), %rdx
callq 0x8d7f0
jmp 0x9a6b1
movq 0x128(%rsp), %rax
movq 0x1b0(%rsp), %rcx
addq 0xa8(%rax), %rcx
movq %rcx, 0xa8(%rax)
jmp 0x9a5d2
movq 0x1b8(%rsp), %rax
movq %rax, 0x30(%rsp)
cmpq $0x0, %rax
je 0x9a6f1
movq 0x30(%rsp), %rdi
callq 0x94de0
jmp 0x9a6f3
jmp 0x9a6f5
jmp 0x9a6f7
movq 0x128(%rsp), %rdi
addq $0x88, %rdi
callq 0x977c0
testb $0x1, %al
jne 0x9a9ae
leaq 0x16f(%rsp), %rdi
movq %rdi, 0x28(%rsp)
callq 0x98200
movq 0x28(%rsp), %rdx
leaq 0x49b4d(%rip), %rsi     # 0xe427e
leaq 0x170(%rsp), %rdi
callq 0x95700
jmp 0x9a740
movq 0x128(%rsp), %rsi
leaq 0x4a015(%rip), %rcx     # 0xe4764
leaq 0x190(%rsp), %rdi
leaq 0x170(%rsp), %rdx
callq 0x984a0
jmp 0x9a766
leaq 0x170(%rsp), %rdi
callq 0x99830
leaq 0x16f(%rsp), %rdi
callq 0x938a0
leaq 0x190(%rsp), %rdi
callq 0x977c0
testb $0x1, %al
jne 0x9a990
leaq 0x49aef(%rip), %rsi     # 0xe428b
leaq 0x190(%rsp), %rdi
callq 0x99740
movb %al, 0x27(%rsp)
jmp 0x9a7af
movb 0x27(%rsp), %al
testb $0x1, %al
jne 0x9a7bc
jmp 0x9a83c
movq 0x128(%rsp), %rdi
movq %rdi, %rsi
addq $0x88, %rsi
callq 0x959a0
jmp 0x9a7d5
jmp 0x9a98e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a811
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
leaq 0x170(%rsp), %rdi
callq 0x99830
leaq 0x16f(%rsp), %rdi
callq 0x938a0
jmp 0x9a9d0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
jmp 0x9a99f
leaq 0x49a6a(%rip), %rsi     # 0xe42ad
leaq 0x190(%rsp), %rdi
callq 0x99740
movb %al, 0x26(%rsp)
jmp 0x9a856
movb 0x26(%rsp), %al
testb $0x1, %al
jne 0x9a887
jmp 0x9a860
leaq 0x49a57(%rip), %rsi     # 0xe42be
leaq 0x190(%rsp), %rdi
callq 0x99740
movb %al, 0x25(%rsp)
jmp 0x9a87a
movb 0x25(%rsp), %al
testb $0x1, %al
jne 0x9a887
jmp 0x9a98c
movq 0x128(%rsp), %rax
addq $0x88, %rax
movq %rax, 0x10(%rsp)
xorl %eax, %eax
movl %eax, %esi
leaq 0x138(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x8e450
movq 0x10(%rsp), %rsi
movq 0x18(%rsp), %rdx
leaq 0x158(%rsp), %rdi
callq 0x8f9d0
jmp 0x9a8c9
movq 0x128(%rsp), %rdi
addq $0xb0, %rdi
leaq 0x158(%rsp), %rsi
callq 0x92ce0
leaq 0x158(%rsp), %rdi
callq 0x90790
leaq 0x138(%rsp), %rdi
callq 0x8f330
jmp 0x9a98a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
leaq 0x138(%rsp), %rdi
callq 0x8f330
movq 0x420(%rsp), %rdi
callq 0x8f0f0
movl $0x8, %edi
callq 0x8f970
movq %rax, %rdi
movq %rdi, 0x8(%rsp)
movq $0x0, (%rdi)
callq 0x8f780
movq 0x8(%rsp), %rdi
movq 0x6b41c(%rip), %rsi     # 0x105d78
movq 0x6b3c5(%rip), %rdx     # 0x105d28
callq 0x97c60
jmp 0x9a9ff
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x420(%rsp)
movl %eax, 0x41c(%rsp)
callq 0x97420
jmp 0x9a988
jmp 0x9a99f
jmp 0x9a98c
jmp 0x9a98e
jmp 0x9a990
leaq 0x190(%rsp), %rdi
callq 0x99830
jmp 0x9a9ae
leaq 0x190(%rsp), %rdi
callq 0x99830
jmp 0x9a9d0
leaq 0x298(%rsp), %rdi
callq 0x8f670
leaq 0x1440(%rsp), %rdi
callq 0x99830
addq $0x1468, %rsp           # imm = 0x1468
retq
leaq 0x298(%rsp), %rdi
callq 0x8f670
leaq 0x1440(%rsp), %rdi
callq 0x99830
movq 0x420(%rsp), %rdi
callq 0x981c0
movq %rax, %rdi
callq 0x9b760
nop