v/vlib/net/websocket/handshake.v

77 lines
2.0 KiB
V

module websocket
fn (mut ws 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 {
mut res := 0
unsafe {
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 (mut ws 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()
}
}