97 lines
2.3 KiB
Plaintext
97 lines
2.3 KiB
Plaintext
// needs to be compiled with -m -C "-lpthread"
|
|
include "std/net.zr"
|
|
|
|
extern pthread_create
|
|
extern pthread_detach
|
|
|
|
struct ConnData
|
|
sock: i64
|
|
addr: str
|
|
|
|
func handle_connection[conn: ConnData] : void
|
|
req := _stackalloc(10001) as str
|
|
n := net.read(conn->sock, req as ptr, 10000)
|
|
if n <= 0
|
|
net.close(conn->sock)
|
|
conn->addr->free()
|
|
(conn as ptr)->free()
|
|
return
|
|
|
|
req[n] = 0
|
|
|
|
pos := req->find("\r\n")
|
|
if pos == -1
|
|
panic("TODO: bad request")
|
|
|
|
first_line := req->substr_n(0, pos)
|
|
parts := first_line->split(" ")
|
|
method := parts->nth(0) as str
|
|
path := parts->nth(1) as str
|
|
|
|
if !method->equal("GET")
|
|
// TODO: method not supported
|
|
return
|
|
|
|
if path->equal("/")
|
|
// TODO: index
|
|
return
|
|
|
|
// TODO: ANY validation
|
|
file_path := "."->concat(path)
|
|
|
|
file_size, ok := os.get_file_size(file_path)
|
|
if !ok
|
|
// TODO: not found
|
|
return
|
|
|
|
fd := _builtin_syscall(SYS_openat, AT_FDCWD, file_path, O_RDONLY, 0)
|
|
if fd < 0
|
|
// TODO: not found
|
|
return
|
|
|
|
resp := "HTTP/1.1 200 OK\r\nConnection: close\r\n\r\n"
|
|
net.send(conn->sock, resp as ptr, resp->len())
|
|
|
|
offset := 0
|
|
while offset < file_size
|
|
sent := _builtin_syscall(SYS_sendfile, conn->sock, fd, ^offset, IP_MAXPACKET)
|
|
if sent <= 0
|
|
break
|
|
|
|
net.close(conn->sock)
|
|
|
|
_builtin_syscall(SYS_close, fd)
|
|
file_path->free()
|
|
first_line->free()
|
|
parts->free_with_items()
|
|
conn->addr->free()
|
|
(conn as ptr)->free()
|
|
|
|
func main[argc: i64, argv: ptr] : i64
|
|
port := 8000
|
|
|
|
if argc > 1
|
|
port = os.arg(argv, 1)->parse_i64()
|
|
|
|
server_sock, ok := net.listen("0.0.0.0", port)
|
|
if !ok
|
|
panic("failed to listen")
|
|
|
|
io.printf("Listening on :%d...\n", port)
|
|
|
|
addr := _stackalloc(16)
|
|
while true
|
|
conn := net.accept(server_sock, addr)
|
|
if conn < 0
|
|
io.println("ERROR: failed to accept connection")
|
|
continue
|
|
|
|
conn_data := new* ConnData
|
|
conn_data->sock = conn
|
|
conn_data->addr = mem.alloc(30) as str
|
|
conn_data->addr->format_into(30, "%d.%d.%d.%d:%d", addr[4], addr[5], addr[6], addr[7], mem.read16be(addr + 2))
|
|
|
|
thread := 0
|
|
pthread_create(^thread, 0, ^handle_connection, conn_data)
|
|
pthread_detach(thread)
|