// File: /workspace/github_c_makefile_star2_O0/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
subq $0x9b0, %rsp            # imm = 0x9B0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x20(%rbp), %rdi
callq 0x2ae0
leaq -0x20(%rbp), %rax
movq %rax, -0x860(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq -0x860(%rbp), %rdi
leaq 0x8a81(%rip), %rdx      # 0xb153
callq 0xa3c0
leaq -0x860(%rbp), %rdi
leaq 0x8a74(%rip), %rsi      # 0xb159
leaq 0x8a70(%rip), %rdx      # 0xb15c
leaq 0x8a7b(%rip), %rcx      # 0xb16e
leaq 0x426(%rip), %r8        # 0x2b20
callq 0xa480
leaq -0x860(%rbp), %rdi
leaq 0x8ab3(%rip), %rsi      # 0xb1c0
leaq 0x8aaf(%rip), %rdx      # 0xb1c3
leaq 0x8ab5(%rip), %rcx      # 0xb1d0
leaq 0x46e(%rip), %r8        # 0x2b90
callq 0xa480
movl -0x8(%rbp), %esi
movq -0x10(%rbp), %rdx
leaq -0x860(%rbp), %rdi
callq 0xa7c0
movq -0x20(%rbp), %rsi
movq -0x18(%rbp), %rdx
leaq 0x8aae(%rip), %rdi      # 0xb1f7
movb $0x0, %al
callq 0x20e0
movq -0x18(%rbp), %rax
movl %eax, %edi
callq 0x25a0
movl %eax, -0x864(%rbp)
leaq -0x8a8(%rbp), %rdi
xorl %esi, %esi
movl $0x40, %edx
callq 0x2130
leaq 0x4d5(%rip), %rax       # 0x2c50
movq %rax, -0x8a0(%rbp)
leaq 0x507(%rip), %rax       # 0x2c90
movq %rax, -0x888(%rbp)
leaq 0x539(%rip), %rax       # 0x2cd0
movq %rax, -0x890(%rbp)
leaq 0x5db(%rip), %rax       # 0x2d80
movq %rax, -0x870(%rbp)
movl -0x864(%rbp), %edi
movl $0xa, %esi
callq 0x21f0
cmpl $0x0, %eax
jge 0x27d7
leaq 0x8a6a(%rip), %rdi      # 0xb232
callq 0x2260
movl $0x1, %edi
callq 0x22a0
jmp 0x27d9
jmp 0x27db
movl -0x864(%rbp), %edi
leaq -0x8b8(%rbp), %rsi
leaq -0x8bc(%rbp), %rdx
callq 0x2270
movl %eax, -0x8c0(%rbp)
cmpl $0x0, -0x8c0(%rbp)
jg 0x2819
leaq 0x8a37(%rip), %rdi      # 0xb241
callq 0x2260
movl $0x1, %edi
callq 0x22a0
movl -0x8b4(%rbp), %edi
callq 0x2090
movq %rax, %rsi
leaq -0x928(%rbp), %rdi
callq 0x2410
leaq -0x948(%rbp), %rdi
xorl %esi, %esi
callq 0x8a40
leaq -0x928(%rbp), %rax
movq %rax, -0x930(%rbp)
movl $0x400, -0x94c(%rbp)    # imm = 0x400
movq %rsp, %rax
movq %rax, -0x958(%rbp)
movq %rsp, %rsi
addq $-0x400, %rsi           # imm = 0xFC00
movq %rsi, -0x9a8(%rbp)
movq %rsi, %rsp
movl -0x8c0(%rbp), %edi
movl $0x400, %edx            # imm = 0x400
xorl %ecx, %ecx
callq 0x2030
movq %rax, -0x960(%rbp)
cmpq $0x0, -0x960(%rbp)
jne 0x28a9
movl $0x5, -0x964(%rbp)
jmp 0x295a
cmpq $-0x1, -0x960(%rbp)
jne 0x28ce
leaq 0x898e(%rip), %rdi      # 0xb248
callq 0x2260
movl $0x2, -0x964(%rbp)
jmp 0x295a
movq -0x9a8(%rbp), %rdx
movq -0x960(%rbp), %rcx
leaq -0x948(%rbp), %rdi
leaq -0x8a8(%rbp), %rsi
callq 0x33e0
movq %rax, -0x970(%rbp)
movq -0x970(%rbp), %rax
cmpq -0x960(%rbp), %rax
je 0x292a
movq 0xc6eb(%rip), %rax      # 0xeff8
movq (%rax), %rdi
leaq 0x8954(%rip), %rsi      # 0xb26b
movb $0x0, %al
callq 0x2190
movl $0x2, -0x964(%rbp)
jmp 0x295a
cmpl $0x0, -0x8c8(%rbp)
jne 0x2944
leaq -0x948(%rbp), %rdi
callq 0x9080
cmpl $0x0, %eax
je 0x2950
movl $0x5, -0x964(%rbp)
jmp 0x295a
movl $0x0, -0x964(%rbp)
movq -0x958(%rbp), %rax
movq %rax, %rsp
movl -0x964(%rbp), %eax
movl %eax, -0x9ac(%rbp)
testl %eax, %eax
je 0x2989
jmp 0x2976
movl -0x9ac(%rbp), %eax
subl $0x2, %eax
je 0x27d9
jmp 0x2987
jmp 0x298e
jmp 0x284f
movl $0x0, -0x974(%rbp)
movq -0x8e0(%rbp), %rdi
leaq 0x88e0(%rip), %rsi      # 0xb286
callq 0x9e70
movq %rax, -0x998(%rbp)
movq -0x920(%rbp), %rax
movq %rax, -0x988(%rbp)
leaq -0x928(%rbp), %rax
addq $0x10, %rax
movq %rax, -0x980(%rbp)
movq -0x928(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x9a0(%rbp)
movl -0x934(%rbp), %edi
shrl $0x10, %edi
andl $0xff, %edi
callq 0x8a00
movq %rax, -0x990(%rbp)
movl -0x934(%rbp), %eax
shrl $0x18, %eax
andl $0x7f, %eax
cmpl $0x0, %eax
je 0x2a53
leaq 0x8a16(%rip), %rax      # 0xb42d
movq %rax, -0x998(%rbp)
leaq 0x8a08(%rip), %rax      # 0xb42d
movq %rax, -0x990(%rbp)
leaq 0x885e(%rip), %rax      # 0xb291
movq %rax, -0x9a0(%rbp)
movl -0x8c0(%rbp), %edi
movl $0x190, %esi            # imm = 0x190
leaq -0x9a0(%rbp), %rdx
callq 0x2db0
jmp 0x2aa9
movl -0x934(%rbp), %eax
shrl $0x10, %eax
andl $0xff, %eax
cmpl $0x1, %eax
je 0x2a7f
movl -0x8c0(%rbp), %edi
movl $0x195, %esi            # imm = 0x195
leaq -0x9a0(%rbp), %rdx
callq 0x2db0
jmp 0x2aa7
movl -0x934(%rbp), %eax
shrl $0x1f, %eax
cmpl $0x0, %eax
je 0x2a8f
jmp 0x2aa5
movl -0x8c0(%rbp), %edi
movq -0x20(%rbp), %rsi
leaq -0x9a0(%rbp), %rdx
callq 0x2ed0
jmp 0x2aa7
jmp 0x2aa9
leaq -0x928(%rbp), %rdi
callq 0x24c0
movl -0x8c0(%rbp), %edi
movl $0x2, %esi
callq 0x20a0
movl -0x8c0(%rbp), %edi
callq 0x2160
jmp 0x27db
nopw %cs:(%rax,%rax)