75 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			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()
 | 
						|
	}
 | 
						|
} |