// File: /workspace/github_c_makefile_star2_O1/marcomorain[P]garcon/garcon.c
// Function: main
int main(int argc, char **argv)
{
  struct options options;
  init_options(&options);

  command_t cmd;
  cmd.data = &options;
  command_init(&cmd, argv[0], "0.0.1");
  command_option(&cmd, "-d", "--directory [arg]", "The root directory to serve files from (default to the current working directory)", set_root);
  command_option(&cmd, "-p", "--port [arg]", "Which port to listen on (default 8888)", set_port);
  command_parse(&cmd, argc, argv);

  printf("Garçon! Serving content from %s on http://localhost:%ld/\n", options.root, options.port);

  const int socket = open_connection(options.port);

  http_parser_settings settings;
  memset(&settings, 0, sizeof(http_parser_settings));
  settings.on_url = on_url;
  settings.on_header_value = on_header_value;
  settings.on_header_field = on_header_field;
  settings.on_message_complete = on_message_complete;

  if (listen(socket, 10) < 0) {
    perror("server: listen");
    exit(EXIT_FAILURE);
  }

    struct sockaddr_in address;
    socklen_t addrlen;

http:
  for(;;) {
    //xkcd.com/292/

    const int new_socket = accept(socket, (struct sockaddr *)&address, &addrlen);

    if (new_socket <= 0) {
      perror("accept");
      exit(EXIT_FAILURE);
    }

    struct parser_data data;
    parser_data_init(&data, inet_ntoa(address.sin_addr));

    // TODO: anything to free()?
    http_parser parser;
    http_parser_init(&parser, HTTP_REQUEST);
    parser.data = &data;

    for (;;) {

      const int len = 1024;
      char buf[len];

      // Read data from the socket
      const ssize_t recved = recv(new_socket, buf, len, 0);

      if (recved == 0) {
        break;
      }

      if (recved == -1) {
        perror("Error reading request from network");
        goto http;
      }
      // Start up / continue the parser. Note we pass recved==0 to
      // signal that EOF has been received.
      const ssize_t nparsed = http_parser_execute(&parser, &settings, buf, recved);

      if (nparsed != recved) {
        fprintf(stderr, "Error parsing HTTP header\n");
        goto http;
      }

      if (data.complete || http_body_is_final(&parser)) {
        break;
      }
    }


     const int headers = 0;

    if (headers) {
      puts("Headers");
      for (struct map_node_t* node = data.headers->head; node; node = node->next) {
        if (node->value) {
          printf("%s: %s\n", node->key, (const char*)node->value);
        }
      }
    }

    struct request request;
    request.user_agent = map_get(data.headers, "User-Agent");
    request.client_address = data.client_address;
    request.time = &data.timeinfo;
    request.uri = data.url->data;
    request.method = http_method_str(parser.method);

    if (parser.http_errno) {
      request.user_agent = "";
      request.method = "";
      request.uri = "BAD REQUEST";
      send_error(new_socket, 400, &request);
    } else if (parser.method != HTTP_GET) {
      send_error(new_socket, 405, &request);
    } else if (parser.upgrade) {
      /* handle new protocol */
    } else {
      send_file(new_socket, options.root, &request);
    }
    parser_data_destroy(&data);
    shutdown(new_socket, SHUT_RDWR);
    close(new_socket);
  }
  close(socket);

  return EXIT_SUCCESS;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xa08, %rsp            # imm = 0xA08
movq %rsi, %rbx
movl %edi, %r14d
leaq -0xf0(%rbp), %r12
movq $0x22b8, 0x8(%r12)      # imm = 0x22B8
xorl %edi, %edi
xorl %esi, %esi
callq 0x2150
movq %rax, (%r12)
leaq -0xa28(%rbp), %r15
movq %r12, (%r15)
movq (%rbx), %rsi
leaq 0x5918(%rip), %rdx      # 0x8153
movq %r15, %rdi
callq 0x6e8e
leaq 0x590f(%rip), %rsi      # 0x8159
leaq 0x590b(%rip), %rdx      # 0x815c
leaq 0x5916(%rip), %rcx      # 0x816e
leaq 0x488(%rip), %r8        # 0x2ce7
movq %r15, %rdi
callq 0x6f01
leaq 0x5952(%rip), %rsi      # 0x81c0
leaq 0x594e(%rip), %rdx      # 0x81c3
leaq 0x5954(%rip), %rcx      # 0x81d0
leaq 0x495(%rip), %r8        # 0x2d18
movq %r15, %rdi
callq 0x6f01
movq %r15, %rdi
movl %r14d, %esi
movq %rbx, %rdx
callq 0x7082
movq (%r12), %rsi
movq 0x8(%r12), %rdx
leaq 0x594e(%rip), %rdi      # 0x81f7
xorl %eax, %eax
callq 0x20f0
movl 0x8(%r12), %edi
callq 0x2765
movl %eax, %r14d
xorps %xmm0, %xmm0
movaps %xmm0, -0xe0(%rbp)
movaps %xmm0, -0xc0(%rbp)
movaps %xmm0, -0xd0(%rbp)
movaps %xmm0, -0xb0(%rbp)
leaq 0x493(%rip), %rax       # 0x2d76
movq %rax, -0xd8(%rbp)
leaq 0x496(%rip), %rax       # 0x2d87
movq %rax, -0xc0(%rbp)
leaq 0x49a(%rip), %rax       # 0x2d99
movq %rax, -0xc8(%rbp)
leaq 0x509(%rip), %rax       # 0x2e16
movq %rax, -0xa8(%rbp)
movl %r14d, %edi
movl $0xa, %esi
callq 0x2200
testl %eax, %eax
jns 0x292e
leaq 0x5906(%rip), %rdi      # 0x8232
jmp 0x2949
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
movl %r14d, %edi
callq 0x2280
testl %eax, %eax
jg 0x2958
leaq 0x58f8(%rip), %rdi      # 0x8241
callq 0x2270
movl $0x1, %edi
callq 0x22b0
movl %eax, %r13d
leaq -0x158(%rbp), %r12
movl %r14d, -0x2c(%rbp)
movl -0x7c(%rbp), %edi
callq 0x20b0
movq %r12, %rdi
movq %rax, %rsi
callq 0x267c
leaq -0xa0(%rbp), %rdi
xorl %esi, %esi
callq 0x5ff5
movq %r12, -0x88(%rbp)
movq %rsp, %r14
movq %rsp, %rbx
addq $-0x400, %rbx           # imm = 0xFC00
movq %rbx, %rsp
movl $0x400, %edx            # imm = 0x400
movl %r13d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x2030
movl $0x5, %r12d
testq %rax, %rax
je 0x2a38
movq %rax, %r15
cmpq $-0x1, %rax
je 0x2a04
leaq -0xa0(%rbp), %rdi
leaq -0xe0(%rbp), %rsi
movq %rbx, %rdx
movq %r15, %rcx
callq 0x3080
cmpq %r15, %rax
jne 0x2a12
cmpl $0x0, -0xf8(%rbp)
jne 0x2a38
leaq -0xa0(%rbp), %rdi
callq 0x64e0
xorl %ecx, %ecx
testl %eax, %eax
setne %cl
leal (%rcx,%rcx,4), %r12d
jmp 0x2a38
leaq 0x583d(%rip), %rdi      # 0x8248
callq 0x2270
jmp 0x2a32
movq 0x95df(%rip), %rax      # 0xbff8
movq (%rax), %rcx
movl $0x1a, %esi
movl $0x1, %edx
leaq 0x583e(%rip), %rdi      # 0x826b
callq 0x22c0
movl $0x2, %r12d
movq %r14, %rsp
testl %r12d, %r12d
je 0x298e
cmpl $0x5, %r12d
jne 0x2ad9
movq -0x110(%rbp), %rdi
leaq 0x582a(%rip), %rsi      # 0x8286
callq 0x6b4c
movq %rax, -0x60(%rbp)
movq -0x158(%rbp), %rax
movq -0x150(%rbp), %rcx
movq %rcx, -0x50(%rbp)
leaq -0x148(%rbp), %rcx
movq %rcx, -0x48(%rbp)
movq 0x10(%rax), %rbx
movq %rbx, -0x68(%rbp)
movzbl -0x8a(%rbp), %edi
callq 0x5fda
movq %rax, -0x58(%rbp)
movl -0x8c(%rbp), %eax
testl $0x7f000000, %eax       # imm = 0x7F000000
movl -0x2c(%rbp), %r14d
leaq -0x158(%rbp), %r12
je 0x2b00
leaq 0x5974(%rip), %rax      # 0x842d
movq %rax, -0x60(%rbp)
movq %rax, -0x58(%rbp)
leaq 0x57c9(%rip), %rax      # 0x8291
movq %rax, -0x68(%rbp)
movl %r13d, %edi
movl $0x190, %esi            # imm = 0x190
jmp 0x2c60
movl -0x2c(%rbp), %edi
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x2280
movl %eax, %r13d
testl %eax, %eax
leaq -0x158(%rbp), %r12
jg 0x2966
jmp 0x2942
movl %eax, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
cmpl $0x10000, %ecx          # imm = 0x10000
jne 0x2c58
testl %eax, %eax
js 0x2c69
movq -0xf0(%rbp), %rax
movq %rax, -0x38(%rbp)
xorl %eax, %eax
callq 0x64fc
movq %rax, %r15
movq %rax, -0x40(%rbp)
movq %rax, %rdi
movq -0x38(%rbp), %rsi
callq 0x67d5
movq %r15, %rdi
movq %rbx, %rsi
callq 0x67d5
leaq -0x40(%rbp), %rdi
callq 0x2726
movq -0x40(%rbp), %r15
movq %r15, %rdi
callq 0x6669
testq %rax, %rax
je 0x2b80
movq 0x10(%r15), %rcx
cmpb $0x2f, -0x1(%rcx,%rax)
jne 0x2b80
movq %r15, %rdi
leaq 0x5940(%rip), %rsi      # 0x84bb
callq 0x67d5
movq 0x10(%r15), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x2260
testl %eax, %eax
jle 0x2ca6
movq %r15, %rdi
movl %eax, %r15d
callq 0x6672
movl %r15d, -0x38(%rbp)
movl %r15d, %edi
leaq -0x1e8(%rbp), %rsi
callq 0x22e0
testl %eax, %eax
jne 0x2cc8
movl -0x1d0(%rbp), %eax
movl $0xf000, %ecx           # imm = 0xF000
andl %ecx, %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x2cb0
movq -0x1b8(%rbp), %rdi
movq %rdi, -0x70(%rbp)
leaq -0x148(%rbp), %rsi
movq %rbx, %rdx
callq 0x2ee5
movq %rax, %rbx
movq 0x10(%rax), %r15
movq %rax, %rdi
callq 0x6669
movl %r13d, %edi
movq %r15, %rsi
movq %rax, %rdx
callq 0x20a0
movq %rbx, %rdi
callq 0x6672
movq $0x0, -0x1e8(%rbp)
movl %r13d, %edi
movl -0x38(%rbp), %r15d
movl %r15d, %esi
leaq -0x1e8(%rbp), %rdx
movq -0x70(%rbp), %rcx
callq 0x2210
movq %rax, %rbx
movl %r15d, %edi
callq 0x2170
cmpq $-0x1, %rbx
je 0x2cba
movl $0xc8, %edi
leaq -0x68(%rbp), %rsi
callq 0x301d
jmp 0x2c69
movl %r13d, %edi
movl $0x195, %esi            # imm = 0x195
leaq -0x68(%rbp), %rdx
callq 0x2e24
movq %r12, %rdi
callq 0x26f5
movl %r13d, %edi
movl $0x2, %esi
callq 0x20c0
movl %r13d, %edi
callq 0x2170
movl %r14d, %edi
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x2280
movl %eax, %r13d
testl %eax, %eax
jg 0x2966
jmp 0x2942
movl %r13d, %edi
movl $0x194, %esi            # imm = 0x194
jmp 0x2c60
movl %r13d, %edi
movl $0x193, %esi            # imm = 0x193
jmp 0x2c60
leaq 0x57b8(%rip), %rdi      # 0x8479
callq 0x2270
jmp 0x2c69
leaq 0x57b3(%rip), %rdi      # 0x8482
leaq 0x57ba(%rip), %rsi      # 0x8490
leaq 0x57bc(%rip), %rcx      # 0x8499
movl $0xf5, %edx
callq 0x2120