// File: /workspace/github_c_makefile_star2_O3/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 0x5948(%rip), %rdx      # 0x8153
movq %r15, %rdi
callq 0x6d15
leaq 0x593f(%rip), %rsi      # 0x8159
leaq 0x593b(%rip), %rdx      # 0x815c
leaq 0x5946(%rip), %rcx      # 0x816e
leaq 0x47e(%rip), %r8        # 0x2cad
movq %r15, %rdi
callq 0x6d88
leaq 0x5982(%rip), %rsi      # 0x81c0
leaq 0x597e(%rip), %rdx      # 0x81c3
leaq 0x5984(%rip), %rcx      # 0x81d0
leaq 0x48b(%rip), %r8        # 0x2cde
movq %r15, %rdi
callq 0x6d88
movq %r15, %rdi
movl %r14d, %esi
movq %rbx, %rdx
callq 0x6f0c
movq (%r12), %rsi
movq 0x8(%r12), %rdx
leaq 0x597e(%rip), %rdi      # 0x81f7
xorl %eax, %eax
callq 0x20f0
movl 0x8(%r12), %edi
callq 0x2735
movl %eax, %ebx
xorps %xmm0, %xmm0
movaps %xmm0, -0xc0(%rbp)
movaps %xmm0, -0xa0(%rbp)
movaps %xmm0, -0xb0(%rbp)
movq $0x0, -0x90(%rbp)
leaq 0x486(%rip), %rax       # 0x2d3c
movq %rax, -0xb8(%rbp)
leaq 0x489(%rip), %rax       # 0x2d4d
movq %rax, -0xa0(%rbp)
leaq 0x48d(%rip), %rax       # 0x2d5f
movq %rax, -0xa8(%rbp)
leaq 0x4fc(%rip), %rax       # 0x2ddc
movq %rax, -0x88(%rbp)
movl %ebx, %edi
movl $0xa, %esi
callq 0x2200
testl %eax, %eax
jns 0x2900
leaq 0x5934(%rip), %rdi      # 0x8232
jmp 0x291a
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
movl %ebx, %edi
callq 0x2280
testl %eax, %eax
jg 0x2929
leaq 0x5927(%rip), %rdi      # 0x8241
callq 0x2270
movl $0x1, %edi
callq 0x22b0
movl %eax, %r14d
leaq -0x158(%rbp), %r13
leaq -0xe0(%rbp), %r12
movl %ebx, -0x2c(%rbp)
movl -0x7c(%rbp), %edi
callq 0x20b0
movq %r13, %rdi
movq %rax, %rsi
callq 0x264c
movq %r12, %rdi
xorl %esi, %esi
callq 0x5ec1
movq %r13, -0xc8(%rbp)
movq %rsp, %r13
movq %rsp, %rbx
addq $-0x400, %rbx           # imm = 0xFC00
movq %rbx, %rsp
movl $0x400, %edx            # imm = 0x400
movl %r14d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x2030
testq %rax, %rax
je 0x29cd
movq %rax, %r15
cmpq $-0x1, %rax
je 0x2c25
movq %r12, %rdi
leaq -0xc0(%rbp), %rsi
movq %rbx, %rdx
movq %r15, %rcx
callq 0x3044
cmpq %r15, %rax
jne 0x2c33
cmpl $0x0, -0xf8(%rbp)
jne 0x29cd
movq %r12, %rdi
callq 0x6395
testl %eax, %eax
jne 0x29cd
movq %r13, %rsp
jmp 0x2961
movq %r13, %rsp
movq -0x110(%rbp), %rdi
leaq 0x58a8(%rip), %rsi      # 0x8286
callq 0x69fc
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 -0xca(%rbp), %edi
callq 0x5ea6
movq %rax, -0x58(%rbp)
movl -0xcc(%rbp), %eax
testl $0x7f000000, %eax       # imm = 0x7F000000
je 0x2a60
leaq 0x59fd(%rip), %rax      # 0x842d
movq %rax, -0x60(%rbp)
movq %rax, -0x58(%rbp)
leaq 0x5852(%rip), %rax      # 0x8291
movq %rax, -0x68(%rbp)
movl %r14d, %edi
movl $0x190, %esi            # imm = 0x190
leaq -0x68(%rbp), %rdx
callq 0x2dea
leaq -0x158(%rbp), %r13
jmp 0x2bd4
movl %eax, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
cmpl $0x10000, %ecx          # imm = 0x10000
leaq -0x158(%rbp), %r13
jne 0x2bc3
testl %eax, %eax
js 0x2bd4
movq -0xf0(%rbp), %rax
movq %rax, -0x38(%rbp)
xorl %eax, %eax
callq 0x63b0
movq %rax, %r15
movq %rax, -0x40(%rbp)
movq %rax, %rdi
movq -0x38(%rbp), %rsi
callq 0x6679
movq %r15, %rdi
movq %rbx, %rsi
callq 0x6679
leaq -0x40(%rbp), %rdi
callq 0x26f6
movq -0x40(%rbp), %r15
movq %r15, %rdi
callq 0x650d
testq %rax, %rax
je 0x2ae7
movq 0x10(%r15), %rcx
cmpb $0x2f, -0x1(%rcx,%rax)
jne 0x2ae7
movq %r15, %rdi
leaq 0x59d9(%rip), %rsi      # 0x84bb
callq 0x6679
movq 0x10(%r15), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x2260
testl %eax, %eax
jle 0x2c11
movq %r15, %rdi
movl %eax, %r15d
callq 0x6516
movl %r15d, -0x38(%rbp)
movl %r15d, %edi
leaq -0x1e8(%rbp), %rsi
callq 0x22e0
testl %eax, %eax
jne 0x2c8e
movl -0x1d0(%rbp), %eax
movl $0xf000, %ecx           # imm = 0xF000
andl %ecx, %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x2c1b
movq -0x1b8(%rbp), %rdi
movq %rdi, -0x70(%rbp)
leaq -0x148(%rbp), %rsi
movq %rbx, %rdx
callq 0x2eab
movq %rax, %rbx
movq 0x10(%rax), %r15
movq %rax, %rdi
callq 0x650d
movl %r14d, %edi
movq %r15, %rsi
movq %rax, %rdx
callq 0x20a0
movq %rbx, %rdi
callq 0x6516
movq $0x0, -0x1e8(%rbp)
movl %r14d, %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 0x2c7d
movl $0xc8, %edi
leaq -0x68(%rbp), %rsi
callq 0x2fe3
jmp 0x2bd4
movl %r14d, %edi
movl $0x195, %esi            # imm = 0x195
leaq -0x68(%rbp), %rdx
callq 0x2dea
movq %r13, %rdi
callq 0x26c5
movl %r14d, %edi
movl $0x2, %esi
callq 0x20c0
movl %r14d, %edi
callq 0x2170
movl -0x2c(%rbp), %edi
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x2280
movl %eax, %r14d
testl %eax, %eax
jg 0x293d
jmp 0x2913
movl %r14d, %edi
movl $0x194, %esi            # imm = 0x194
jmp 0x2bcb
movl %r14d, %edi
movl $0x193, %esi            # imm = 0x193
jmp 0x2bcb
leaq 0x561c(%rip), %rdi      # 0x8248
callq 0x2270
jmp 0x2c53
movq 0x93be(%rip), %rax      # 0xbff8
movq (%rax), %rcx
movl $0x1a, %esi
movl $0x1, %edx
leaq 0x561d(%rip), %rdi      # 0x826b
callq 0x22c0
movq %r13, %rsp
movl -0x2c(%rbp), %edi
leaq -0x80(%rbp), %rsi
leaq -0x30(%rbp), %rdx
callq 0x2280
movl %eax, %r14d
testl %eax, %eax
leaq -0x158(%rbp), %r13
jg 0x293d
jmp 0x2913
leaq 0x57f5(%rip), %rdi      # 0x8479
callq 0x2270
jmp 0x2bd4
leaq 0x57ed(%rip), %rdi      # 0x8482
leaq 0x57f4(%rip), %rsi      # 0x8490
leaq 0x57f6(%rip), %rcx      # 0x8499
movl $0xf5, %edx
callq 0x2120