v/vlib/net/websocket/handshake.v

75 lines
1.9 KiB
V

module websocket
fn (ws mut Client) read_handshake(seckey string){
l.d("reading handshake...")
mut bytes_read := 0
max_buffer := 1024
buffer_size := 1
mut buffer := malloc(max_buffer)
for bytes_read <= max_buffer {
res := ws.read_from_server(buffer + bytes_read, buffer_size)
if res == 0 || res == -1 {
l.f("read_handshake: Failed to read handshake.")
}
if buffer[bytes_read] == `\n` && buffer[bytes_read-1] == `\r` && buffer[bytes_read-2] == `\n` && buffer[bytes_read-3] == `\r` {
break
}
bytes_read += buffer_size
}
buffer[max_buffer+1] = `\0`
ws.handshake_handler(string(byteptr(buffer)), seckey)
}
fn (ws mut Client) handshake_handler(handshake_response, seckey string){
l.d("handshake_handler:\r\n${handshake_response}")
lines := handshake_response.split_into_lines()
header := lines[0]
if !header.starts_with("HTTP/1.1 101") && !header.starts_with("HTTP/1.0 101") {
l.f("handshake_handler: invalid HTTP status response code")
}
for i in 1..lines.len {
if lines[i].len <= 0 || lines[i] == "\r\n" {
continue
}
keys := lines[i].split(":")
match keys[0] {
"Upgrade", "upgrade" {
ws.flags << .has_upgrade
}
"Connection", "connection" {
ws.flags << .has_connection
}
"Sec-WebSocket-Accept", "sec-websocket-accept" {
l.d("comparing hashes")
l.d("seckey: ${seckey}")
challenge := create_key_challenge_response(seckey)
l.d("challenge: ${challenge}")
l.d("response: ${keys[1]}")
if keys[1].trim_space() != challenge {
l.e("handshake_handler: Sec-WebSocket-Accept header does not match computed sha1/base64 response.")
}
ws.flags << .has_accept
unsafe {
challenge.free()
}
} else {}
}
unsafe {
keys.free()
}
}
if ws.flags.len < 3 {
ws.close(1002, "invalid websocket HTTP headers")
l.e("invalid websocket HTTP headers")
}
l.i("handshake successful!")
unsafe {
handshake_response.free()
lines.free()
header.free()
}
}