// File: /workspace/github_c_makefile_star2_O2/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 -0xe0(%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 0x4b4b(%rip), %rdx      # 0x7153
movq %r15, %rdi
callq 0x69d8
leaq 0x4b42(%rip), %rsi      # 0x7159
leaq 0x4b3e(%rip), %rdx      # 0x715c
leaq 0x4b49(%rip), %rcx      # 0x716e
leaq 0x414(%rip), %r8        # 0x2a40
movq %r15, %rdi
callq 0x6a4d
leaq 0x4b85(%rip), %rsi      # 0x71c0
leaq 0x4b81(%rip), %rdx      # 0x71c3
leaq 0x4b87(%rip), %rcx      # 0x71d0
leaq 0x439(%rip), %r8        # 0x2a89
movq %r15, %rdi
callq 0x6a4d
movq %r15, %rdi
movl %r14d, %esi
movq %rbx, %rdx
callq 0x6bfd
movq (%r12), %rsi
movq 0x8(%r12), %rdx
leaq 0x4b81(%rip), %rdi      # 0x71f7
xorl %eax, %eax
callq 0x20f0
movl 0x8(%r12), %edi
callq 0x2512
movl %eax, %edi
xorps %xmm0, %xmm0
movaps %xmm0, -0xb0(%rbp)
movaps %xmm0, -0x90(%rbp)
movaps %xmm0, -0xa0(%rbp)
andq $0x0, -0x80(%rbp)
leaq 0x467(%rip), %rax       # 0x2b14
movq %rax, -0xa8(%rbp)
leaq 0x46a(%rip), %rax       # 0x2b25
movq %rax, -0x90(%rbp)
leaq 0x46e(%rip), %rax       # 0x2b37
movq %rax, -0x98(%rbp)
leaq 0x4dd(%rip), %rax       # 0x2bb4
movq %rax, -0x78(%rbp)
pushq $0xa
popq %rsi
movl %edi, -0x2c(%rbp)
callq 0x2200
testl %eax, %eax
jns 0x26f6
leaq 0x4b41(%rip), %rdi      # 0x7232
jmp 0x2a14
leaq -0xd0(%rbp), %r14
movl -0x2c(%rbp), %edi
leaq -0xf0(%rbp), %rsi
leaq -0x6c(%rbp), %rdx
callq 0x2280
testl %eax, %eax
jle 0x2a0d
movl %eax, %r15d
movl -0xec(%rbp), %edi
callq 0x20b0
leaq -0x158(%rbp), %rbx
movq %rbx, %rdi
movq %rax, %rsi
callq 0x242c
movq %r14, %rdi
xorl %esi, %esi
callq 0x5c69
movq %rbx, -0xb8(%rbp)
movq %rsp, %r12
movq %rsp, %rbx
addq $-0x400, %rbx           # imm = 0xFC00
movq %rbx, %rsp
movl $0x400, %edx            # imm = 0x400
movl %r15d, %edi
movq %rbx, %rsi
xorl %ecx, %ecx
callq 0x2030
testq %rax, %rax
je 0x27b5
movq %rax, %r13
cmpq $-0x1, %rax
je 0x29cd
movq %r14, %rdi
leaq -0xb0(%rbp), %rsi
movq %rbx, %rdx
movq %r13, %rcx
callq 0x2e78
cmpq %r13, %rax
jne 0x29db
cmpl $0x0, -0xf8(%rbp)
jne 0x27b5
movq %r14, %rdi
callq 0x60f4
testl %eax, %eax
jne 0x27b5
movq %r12, %rsp
jmp 0x2749
movq %r12, %rsp
movq -0x110(%rbp), %rdi
leaq 0x4ac0(%rip), %rsi      # 0x7286
callq 0x66e1
movq %rax, -0x58(%rbp)
movq -0x158(%rbp), %rax
movq -0x150(%rbp), %rcx
movq %rcx, -0x48(%rbp)
leaq -0x148(%rbp), %rcx
movq %rcx, -0x40(%rbp)
movq 0x10(%rax), %rbx
movq %rbx, -0x60(%rbp)
movzbl -0xba(%rbp), %edi
callq 0x5c4e
movq %rax, -0x50(%rbp)
movl -0xbc(%rbp), %eax
testl $0x7f000000, %eax       # imm = 0x7F000000
je 0x2838
leaq 0x4c15(%rip), %rax      # 0x742d
movq %rax, -0x58(%rbp)
movq %rax, -0x50(%rbp)
leaq 0x4a6a(%rip), %rax      # 0x7291
movq %rax, -0x60(%rbp)
movl %r15d, %edi
movl $0x190, %esi            # imm = 0x190
jmp 0x298c
movl %eax, %ecx
andl $0xff0000, %ecx         # imm = 0xFF0000
cmpl $0x10000, %ecx          # imm = 0x10000
jne 0x2984
testl %eax, %eax
js 0x2995
movq -0xe0(%rbp), %r12
xorl %eax, %eax
callq 0x6110
movq %rax, %r13
movq %rax, -0x38(%rbp)
movq %rax, %rdi
movq %r12, %rsi
callq 0x63a2
movq %r13, %rdi
movq %rbx, %rsi
callq 0x63a2
leaq -0x38(%rbp), %rdi
callq 0x24d3
movq -0x38(%rbp), %r13
movq %r13, %rdi
callq 0x623e
testq %rax, %rax
je 0x28b3
movq 0x10(%r13), %rcx
cmpb $0x2f, -0x1(%rcx,%rax)
jne 0x28b3
movq %r13, %rdi
leaq 0x4c0d(%rip), %rsi      # 0x74bb
callq 0x63a2
movq 0x10(%r13), %rdi
xorl %esi, %esi
xorl %eax, %eax
callq 0x2260
testl %eax, %eax
jle 0x29b9
movl %eax, %r12d
movq %r13, %rdi
callq 0x6247
movl %r12d, %edi
leaq -0x1e8(%rbp), %rsi
callq 0x22e0
testl %eax, %eax
jne 0x2a21
movl -0x1d0(%rbp), %eax
movl $0xf000, %ecx           # imm = 0xF000
andl %ecx, %eax
cmpl $0x8000, %eax           # imm = 0x8000
jne 0x29c3
movq -0x1b8(%rbp), %rdi
movq %rdi, -0x68(%rbp)
leaq -0x148(%rbp), %rsi
movq %rbx, %rdx
callq 0x2cab
movq %rax, %rbx
movq 0x10(%rax), %r13
movq %rax, %rdi
callq 0x623e
movl %r15d, %edi
movq %r13, %rsi
movq %rax, %rdx
callq 0x20a0
movq %rbx, %rdi
callq 0x6247
andq $0x0, -0x1e8(%rbp)
movl %r15d, %edi
movl %r12d, %esi
leaq -0x1e8(%rbp), %rdx
movq -0x68(%rbp), %rcx
callq 0x2210
movq %rax, %rbx
movl %r12d, %edi
callq 0x2170
cmpq $-0x1, %rbx
je 0x29ff
movl $0xc8, %edi
leaq -0x60(%rbp), %rsi
callq 0x2dfa
jmp 0x2995
movl %r15d, %edi
movl $0x195, %esi            # imm = 0x195
leaq -0x60(%rbp), %rdx
callq 0x2bc2
leaq -0x158(%rbp), %rdi
callq 0x24a2
movl %r15d, %edi
pushq $0x2
popq %rsi
callq 0x20c0
movl %r15d, %edi
callq 0x2170
jmp 0x26fd
movl %r15d, %edi
movl $0x194, %esi            # imm = 0x194
jmp 0x298c
movl %r15d, %edi
movl $0x193, %esi            # imm = 0x193
jmp 0x298c
leaq 0x4874(%rip), %rdi      # 0x7248
callq 0x2270
jmp 0x29f7
movq 0x8616(%rip), %rax      # 0xaff8
movq (%rax), %rcx
leaq 0x487f(%rip), %rdi      # 0x726b
pushq $0x1a
popq %rsi
pushq $0x1
popq %rdx
callq 0x22c0
movq %r12, %rsp
jmp 0x26fd
leaq 0x4a73(%rip), %rdi      # 0x7479
callq 0x2270
jmp 0x2995
leaq 0x482d(%rip), %rdi      # 0x7241
callq 0x2270
pushq $0x1
popq %rdi
callq 0x22b0
leaq 0x4a5a(%rip), %rdi      # 0x7482
leaq 0x4a61(%rip), %rsi      # 0x7490
leaq 0x4a63(%rip), %rcx      # 0x7499
movl $0xf5, %edx
callq 0x2120