// File: /workspace/github_c_makefile_star2_O3/howerj[P]eweb/eweb.c
// Function: eweb_hit
int eweb_hit(eweb_os_t *w, eweb_os_hit_args_t *args) {
	assert(w);
	assert(args);

	long i = 0, request_size = 0;
	args->buffer = string_new(w, READ_BUF_LEN);
	if (!args->buffer) {
		return EWEB_ERROR;
	}

	/* We need to read the HTTP headers first so loop until we receive "\r\n\r\n" */
	while (eweb_get_body_start(string_chars(w, args->buffer)) < 0 && args->buffer->used_bytes <= MAX_INCOMING_REQUEST) {
		char buf[READ_BUF_LEN + 1] = { 0 };
		const long rd = w->read(w, args->socketfd, buf, READ_BUF_LEN); // !!
		request_size += rd;
		string_add(w, args->buffer, buf); // !!
		if (buf[0] == 0)
			break;
	}

	if (request_size == 0)
		return eweb_finish_hit(w, args, 3);

	eweb_http_header_t content_length = eweb_get_header("Content-Length", string_chars(w, args->buffer), args->buffer->used_bytes);
	args->content_length   = atol(content_length.value);
	const long body_start  = eweb_get_body_start(string_chars(w, args->buffer)); // !?
	const long headers_end = body_start - 4;
	long body_size         = body_start >= 0 ? request_size - body_start : 0;

	if (headers_end > 0) {
		args->headers = eweb_malloc_or_die(w, headers_end + 1); // !!
		strncpy(args->headers, string_chars(w, args->buffer), headers_end);
		args->headers[headers_end] = 0;
	} else {
		args->headers = eweb_malloc_or_die(w, 1); // !!
		args->headers[0] = 0;
	}

	/* safari seems to send the headers, and then the body slightly later */
	while (body_size < args->content_length && args->buffer->used_bytes <= MAX_INCOMING_REQUEST) {
		char buf[READ_BUF_LEN + 1] = { 0 };
		i = w->read(w, args->socketfd, buf, READ_BUF_LEN);
		if (i > 0) {
			request_size += i;
			string_add(w, args->buffer, buf); // !!
			body_size = request_size - body_start;
		} else {
			/* stop looping if we cannot read any more bytes */
			break;
		}
	}

	if (request_size <= 0) { /* cannot read request, so we'll stop */
		if (eweb_forbidden_403(w, args, "failed to read http request") != EWEB_OK) // !? Odd error message...
			return EWEB_ERROR; // !! call eweb_finish_hit??
		return eweb_finish_hit(w, args, 3);
	}

	//w->log(w, EWEB_OK, "request: %s/%ld", string_chars(w, args->buffer), args->hit);

	const http_verb type = eweb_request_type(string_chars(w, args->buffer));
	if (type == EWEB_RT_HTTP_NOT_SUPPORTED_E) {
		if (eweb_forbidden_403(w, args, "Only simple GET and POST operations are supported") != EWEB_OK)
			return EWEB_ERROR;
		return eweb_finish_hit(w, args, 3);
	}
	/* get a pointer to the request body (or NULL if it's not there) */
	char *body = (type == EWEB_RT_HTTP_GET_E) ? NULL : (char*)args->buffer->ptr + eweb_get_body_start(string_chars(w, args->buffer));

	/* the request will be "GET [URL] " or "POST [URL] " followed by other details
	we will terminate after the second space, to ignore everything else */
	for (i = (type == EWEB_RT_HTTP_GET_E) ? 4 : 5; i < args->buffer->used_bytes; i++) {
		if (string_chars(w, args->buffer)[i] == ' ') {
			string_chars(w, args->buffer)[i] = 0;	/* second space, terminate string here */
			break;
		}
	}

	long j = (type == EWEB_RT_HTTP_GET_E) ? 4 : 5;

	/* check for an absolute directory */
	if (string_chars(w, args->buffer)[j + 1] == '/') {
		if (eweb_forbidden_403(w, args, "Absolute paths are not permitted") != EWEB_OK)
			return EWEB_ERROR;
		return eweb_finish_hit(w, args, 3);
	}

	for (; j < i - 1; j++) {
		/* check for any parent directory use */
		if (string_chars(w, args->buffer)[j] == '.' && string_chars(w, args->buffer)[j + 1] == '.') {
			if (eweb_forbidden_403(w, args, "Parent paths (..) are not permitted") != EWEB_OK)
				return EWEB_ERROR;
			return eweb_finish_hit(w, args, 3);
		}
	}

	eweb_http_header_t ctype = eweb_get_header("Content-Type", args->headers, strlen(args->headers));
	j = strlen(ctype.value);
	if (j > 0) {
		args->content_type = eweb_malloc_or_die(w, j + 1); // !!
		strncpy(args->content_type, ctype.value, j);
		if (eweb_string_matches_value(args->content_type, "application/x-www-form-urlencoded"))
			eweb_get_form_values(w, args, body);
	} else {
		args->content_type = eweb_malloc_or_die(w, 1); // !!
		args->content_type[0] = 0;
	}

	/* call the "responder function" which has been provided to do the rest */
	args->responder_function(w, args, string_chars(w, args->buffer) + ((type == EWEB_RT_HTTP_GET_E) ? 5 : 6), body, type);
	return eweb_finish_hit(w, args, 1);
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x288, %rsp            # imm = 0x288
testq %rdi, %rdi
je 0x3963
movq %rsi, %rbx
testq %rsi, %rsi
je 0x3982
movq %rdi, %r14
movl $0xff, %esi
callq 0x2f21
movq %rax, 0x8(%rbx)
testq %rax, %rax
je 0x3680
xorl %r13d, %r13d
leaq 0x10(%rsp), %r15
movq (%rax), %rdi
callq 0x39c0
testq %rax, %rax
jns 0x35ea
movq 0x8(%rbx), %rax
cmpq $0x1000, 0x10(%rax)     # imm = 0x1000
jg 0x35ea
movl $0x100, %edx            # imm = 0x100
movq %r15, %rdi
xorl %esi, %esi
callq 0x2100
movl 0x40(%rbx), %esi
movl $0xff, %ecx
movq %r14, %rdi
movq %r15, %rdx
callq *0x38(%r14)
addq %rax, %r13
movq 0x8(%rbx), %rsi
movq %r14, %rdi
movq %r15, %rdx
callq 0x2fcc
cmpb $0x0, 0x10(%rsp)
je 0x35ea
movq 0x8(%rbx), %rax
testq %rax, %rax
jne 0x356d
leaq 0x2daa(%rip), %rdi      # 0x637c
leaq 0x22b2(%rip), %rsi      # 0x588b
leaq 0x2b1a(%rip), %rcx      # 0x60fa
movl $0x24a, %edx            # imm = 0x24A
callq 0x20e0
testq %r13, %r13
je 0x383e
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x35cb
movq (%rax), %rdx
movq 0x10(%rax), %rcx
leaq 0x2717(%rip), %rsi      # 0x5d21
leaq 0x10(%rsp), %rdi
callq 0x340e
leaq 0x42(%rsp), %rdi
callq 0x2260
movq %rax, 0x28(%rbx)
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x35cb
movq (%rax), %rdi
callq 0x39c0
movq %rax, %r15
movq %r13, %rax
subq %r15, %rax
xorl %ebp, %ebp
testq %r15, %r15
cmovnsq %rax, %rbp
cmpq $0x5, %r15
jl 0x368a
leaq -0x3(%r15), %rsi
movq %r14, %rdi
callq 0x3a6c
movq %rax, 0x10(%rbx)
movq 0x8(%rbx), %rcx
testq %rcx, %rcx
je 0x35cb
leaq -0x4(%r15), %r12
movq (%rcx), %rsi
movq %rax, %rdi
movq %r12, %rdx
callq 0x2060
addq 0x10(%rbx), %r12
jmp 0x369e
movl $0x1, %eax
jmp 0x3850
movl $0x1, %esi
movq %r14, %rdi
callq 0x3a6c
movq %rax, %r12
movq %rax, 0x10(%rbx)
movb $0x0, (%r12)
cmpq 0x28(%rbx), %rbp
jge 0x3703
leaq 0x150(%rsp), %r12
movq 0x8(%rbx), %rax
cmpq $0x1000, 0x10(%rax)     # imm = 0x1000
jg 0x3703
movl $0x100, %edx            # imm = 0x100
movq %r12, %rdi
xorl %esi, %esi
callq 0x2100
movl 0x40(%rbx), %esi
movl $0xff, %ecx
movq %r14, %rdi
movq %r12, %rdx
callq *0x38(%r14)
testq %rax, %rax
jle 0x3703
addq %rax, %r13
movq 0x8(%rbx), %rsi
movq %r14, %rdi
movq %r12, %rdx
callq 0x2fcc
movq %r13, %rax
subq %r15, %rax
cmpq 0x28(%rbx), %rax
jl 0x36b1
testq %r13, %r13
jle 0x37a9
movq 0x8(%rbx), %r12
testq %r12, %r12
je 0x35cb
movq (%r12), %r13
testq %r13, %r13
je 0x39a1
leaq 0x2a4a(%rip), %rsi      # 0x6177
movl $0x4, %ebp
movl $0x4, %edx
movq %r13, %rdi
callq 0x2070
movl $0x65, %esi
movl $0x5, %r15d
testl %eax, %eax
je 0x37b2
leaq 0x2a27(%rip), %rsi      # 0x617c
movl $0x4, %ebp
movl $0x4, %edx
movq %r13, %rdi
callq 0x2070
testl %eax, %eax
je 0x37d5
leaq 0x2a0f(%rip), %rsi      # 0x6181
movl $0x5, %ebp
movl $0x5, %edx
movq %r13, %rdi
callq 0x2070
testl %eax, %eax
je 0x37b6
leaq 0x29f8(%rip), %rsi      # 0x6187
movl $0x5, %edx
movq %r13, %rdi
callq 0x2070
testl %eax, %eax
je 0x37b6
leaq 0x25a5(%rip), %rdx      # 0x5d4c
jmp 0x3828
leaq 0x2580(%rip), %rdx      # 0x5d30
jmp 0x3828
xorl %edi, %edi
jmp 0x37dc
movq %r13, %rdi
callq 0x39c0
addq %r13, %rax
movq %rax, %rdi
movq 0x8(%rbx), %r12
movl $0x66, %esi
movl $0x6, %r15d
jmp 0x37dc
xorl %edi, %edi
movl $0x65, %esi
movq 0x10(%r12), %rcx
cmpq %rcx, %rbp
jge 0x3800
movq (%r12), %rdx
movq %rbp, %rax
cmpb $0x20, (%rdx,%rax)
je 0x3805
incq %rax
cmpq %rax, %rcx
jne 0x37ed
movq %rcx, %rax
jmp 0x380d
movq %rbp, %rax
jmp 0x3816
movb $0x0, (%rdx,%rax)
movq 0x8(%rbx), %r12
testq %r12, %r12
je 0x35cb
movq (%r12), %rcx
cmpb $0x2f, 0x1(%rcx,%rbp)
jne 0x3862
leaq 0x2556(%rip), %rdx      # 0x5d7e
movq %r14, %rdi
movq %rbx, %rsi
callq 0x31b1
movl %eax, %ecx
movl $0x1, %eax
testl %ecx, %ecx
jne 0x3850
movq %r14, %rdi
movq %rbx, %rsi
movl $0x3, %edx
callq 0x3a0f
xorl %eax, %eax
addq $0x288, %rsp            # imm = 0x288
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq -0x1(%rax), %rdx
cmpq %rdx, %rbp
jge 0x3887
incq %rbp
cmpb $0x2e, -0x1(%rcx,%rbp)
jne 0x387f
cmpb $0x2e, (%rcx,%rbp)
je 0x3957
incq %rbp
cmpq %rbp, %rax
jne 0x386e
movq %rdi, %r12
movl %esi, 0xc(%rsp)
movq 0x10(%rbx), %r13
movq %r13, %rdi
callq 0x20b0
leaq 0x2522(%rip), %rsi      # 0x5dc3
leaq 0x150(%rsp), %rdi
movq %r13, %rdx
movq %rax, %rcx
callq 0x340e
leaq 0x182(%rsp), %r13
movq %r13, %rdi
callq 0x20b0
testq %rax, %rax
jle 0x3910
movq %rax, %rbp
movq %rax, %rsi
incq %rsi
movq %r14, %rdi
callq 0x3a6c
movq %rax, 0x18(%rbx)
movq %rax, %rdi
movq %r13, %rsi
movq %rbp, %rdx
callq 0x2060
movq 0x18(%rbx), %rdi
leaq 0x1cd2(%rip), %rsi      # 0x55c9
callq 0x3b03
testl %eax, %eax
je 0x3924
movq %r14, %rdi
movq %rbx, %rsi
movq %r12, %rdx
callq 0x3b46
jmp 0x3924
movl $0x1, %esi
movq %r14, %rdi
callq 0x3a6c
movq %rax, 0x18(%rbx)
movb $0x0, (%rax)
movq 0x8(%rbx), %rax
testq %rax, %rax
je 0x35cb
addq (%rax), %r15
movq %r14, %rdi
movq %rbx, %rsi
movq %r15, %rdx
movq %r12, %rcx
movl 0xc(%rsp), %r8d
callq *(%rbx)
movq %r14, %rdi
movq %rbx, %rsi
movl $0x1, %edx
jmp 0x3849
leaq 0x2441(%rip), %rdx      # 0x5d9f
jmp 0x3828
leaq 0x1bc3(%rip), %rdi      # 0x552d
leaq 0x1f1a(%rip), %rsi      # 0x588b
leaq 0x2379(%rip), %rcx      # 0x5cf1
movl $0xfa, %edx
callq 0x20e0
leaq 0x1fb3(%rip), %rdi      # 0x593c
leaq 0x1efb(%rip), %rsi      # 0x588b
leaq 0x235a(%rip), %rcx      # 0x5cf1
movl $0xfb, %edx
callq 0x20e0
leaq 0x1c19(%rip), %rdi      # 0x55c1
leaq 0x1edc(%rip), %rsi      # 0x588b
leaq 0x2797(%rip), %rcx      # 0x614d
movl $0xf0, %edx
callq 0x20e0