1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

all: change optional to result of io (#16075)

This commit is contained in:
yuyi
2022-10-16 14:28:57 +08:00
committed by GitHub
parent 6e46933c55
commit f6844e9766
187 changed files with 1885 additions and 1874 deletions

View File

@@ -32,26 +32,26 @@ struct CloseEventHandler {
ref voidptr // referenced object
}
pub type AcceptClientFn = fn (mut c ServerClient) ?bool
pub type AcceptClientFn = fn (mut c ServerClient) !bool
pub type SocketMessageFn = fn (mut c Client, msg &Message) ?
pub type SocketMessageFn = fn (mut c Client, msg &Message) !
pub type SocketMessageFn2 = fn (mut c Client, msg &Message, v voidptr) ?
pub type SocketMessageFn2 = fn (mut c Client, msg &Message, v voidptr) !
pub type SocketErrorFn = fn (mut c Client, err string) ?
pub type SocketErrorFn = fn (mut c Client, err string) !
pub type SocketErrorFn2 = fn (mut c Client, err string, v voidptr) ?
pub type SocketErrorFn2 = fn (mut c Client, err string, v voidptr) !
pub type SocketOpenFn = fn (mut c Client) ?
pub type SocketOpenFn = fn (mut c Client) !
pub type SocketOpenFn2 = fn (mut c Client, v voidptr) ?
pub type SocketOpenFn2 = fn (mut c Client, v voidptr) !
pub type SocketCloseFn = fn (mut c Client, code int, reason string) ?
pub type SocketCloseFn = fn (mut c Client, code int, reason string) !
pub type SocketCloseFn2 = fn (mut c Client, code int, reason string, v voidptr) ?
pub type SocketCloseFn2 = fn (mut c Client, code int, reason string, v voidptr) !
// on_connect registers a callback when client connects to the server
pub fn (mut s Server) on_connect(fun AcceptClientFn) ? {
pub fn (mut s Server) on_connect(fun AcceptClientFn) ! {
if s.accept_client_callbacks.len > 0 {
return error('only one callback can be registered for accept client')
}
@@ -156,13 +156,13 @@ pub fn (mut ws Client) on_close_ref(fun SocketCloseFn2, ref voidptr) {
}
// send_connect_event invokes the on_connect callback
fn (mut s Server) send_connect_event(mut c ServerClient) ?bool {
fn (mut s Server) send_connect_event(mut c ServerClient) !bool {
if s.accept_client_callbacks.len == 0 {
// If no callback all client will be accepted
return true
}
fun := s.accept_client_callbacks[0]
res := fun(mut c)?
res := fun(mut c)!
return res
}

View File

@@ -5,7 +5,7 @@ import encoding.base64
import strings
// handshake manages the websocket handshake process
fn (mut ws Client) handshake() ? {
fn (mut ws Client) handshake() ! {
nonce := get_nonce(ws.nonce_size)
seckey := base64.encode_str(nonce)
mut sb := strings.new_builder(1024)
@@ -34,21 +34,21 @@ fn (mut ws Client) handshake() ? {
}
handshake_bytes := handshake.bytes()
ws.debug_log('sending handshake: $handshake')
ws.socket_write(handshake_bytes)?
ws.read_handshake(seckey)?
ws.socket_write(handshake_bytes)!
ws.read_handshake(seckey)!
unsafe { handshake_bytes.free() }
}
// handle_server_handshake manages websocket server handshake process
fn (mut s Server) handle_server_handshake(mut c Client) ?(string, &ServerClient) {
msg := c.read_handshake_str()?
handshake_response, client := s.parse_client_handshake(msg, mut c)?
fn (mut s Server) handle_server_handshake(mut c Client) !(string, &ServerClient) {
msg := c.read_handshake_str()!
handshake_response, client := s.parse_client_handshake(msg, mut c)!
unsafe { msg.free() }
return handshake_response, client
}
// parse_client_handshake parses result from handshake process
fn (mut s Server) parse_client_handshake(client_handshake string, mut c Client) ?(string, &ServerClient) {
fn (mut s Server) parse_client_handshake(client_handshake string, mut c Client) !(string, &ServerClient) {
s.logger.debug('server-> client handshake:\n$client_handshake')
lines := client_handshake.split_into_lines()
get_tokens := lines[0].split(' ')
@@ -81,7 +81,7 @@ fn (mut s Server) parse_client_handshake(client_handshake string, mut c Client)
'Sec-WebSocket-Key', 'sec-websocket-key' {
key = keys[1].trim_space()
s.logger.debug('server-> got key: $key')
seckey = create_key_challenge_response(key)?
seckey = create_key_challenge_response(key)!
s.logger.debug('server-> challenge: $seckey, response: ${keys[1]}')
flags << .has_accept
}
@@ -112,12 +112,12 @@ fn (mut s Server) parse_client_handshake(client_handshake string, mut c Client)
}
// read_handshake_str returns the handshake response
fn (mut ws Client) read_handshake_str() ?string {
fn (mut ws Client) read_handshake_str() !string {
mut total_bytes_read := 0
mut msg := [1024]u8{}
mut buffer := [1]u8{}
for total_bytes_read < 1024 {
bytes_read := ws.socket_read_ptr(&buffer[0], 1)?
bytes_read := ws.socket_read_ptr(&buffer[0], 1)!
if bytes_read == 0 {
return error_with_code('unexpected no response from handshake', 5)
}
@@ -134,15 +134,15 @@ fn (mut ws Client) read_handshake_str() ?string {
}
// read_handshake reads the handshake result and check if valid
fn (mut ws Client) read_handshake(seckey string) ? {
mut msg := ws.read_handshake_str()?
ws.check_handshake_response(msg, seckey)?
fn (mut ws Client) read_handshake(seckey string) ! {
mut msg := ws.read_handshake_str()!
ws.check_handshake_response(msg, seckey)!
unsafe { msg.free() }
}
// check_handshake_response checks the response from handshake and returns
// the response and secure key provided by the websocket client
fn (mut ws Client) check_handshake_response(handshake_response string, seckey string) ? {
fn (mut ws Client) check_handshake_response(handshake_response string, seckey string) ! {
ws.debug_log('handshake response:\n$handshake_response')
lines := handshake_response.split_into_lines()
header := lines[0]
@@ -164,7 +164,7 @@ fn (mut ws Client) check_handshake_response(handshake_response string, seckey st
}
'Sec-WebSocket-Accept', 'sec-websocket-accept' {
ws.debug_log('seckey: $seckey')
challenge := create_key_challenge_response(seckey)?
challenge := create_key_challenge_response(seckey)!
ws.debug_log('challenge: $challenge, response: ${keys[1]}')
if keys[1].trim_space() != challenge {
return error_with_code('handshake_handler: Sec-WebSocket-Accept header does not match computed sha1/base64 response.',
@@ -179,7 +179,7 @@ fn (mut ws Client) check_handshake_response(handshake_response string, seckey st
}
unsafe { lines.free() }
if ws.flags.len < 3 {
ws.close(1002, 'invalid websocket HTTP headers')?
ws.close(1002, 'invalid websocket HTTP headers')!
return error_with_code('invalid websocket HTTP headers', 8)
}
}

View File

@@ -3,41 +3,41 @@ module websocket
import net
// socket_read reads from socket into the provided buffer
fn (mut ws Client) socket_read(mut buffer []u8) ?int {
fn (mut ws Client) socket_read(mut buffer []u8) !int {
lock {
if ws.state in [.closed, .closing] || ws.conn.sock.handle <= 1 {
return error('socket_read: trying to read a closed socket')
}
if ws.is_ssl {
r := ws.ssl_conn.read(mut buffer) or { return none }
r := ws.ssl_conn.read(mut buffer) or { return error('none') }
return r
} else {
r := ws.conn.read(mut buffer) or { return none }
r := ws.conn.read(mut buffer) or { return error('none') }
return r
}
}
return none
return error('none')
}
// socket_read reads from socket into the provided byte pointer and length
fn (mut ws Client) socket_read_ptr(buf_ptr &u8, len int) ?int {
fn (mut ws Client) socket_read_ptr(buf_ptr &u8, len int) !int {
lock {
if ws.state in [.closed, .closing] || ws.conn.sock.handle <= 1 {
return error('socket_read_ptr: trying to read a closed socket')
}
if ws.is_ssl {
r := ws.ssl_conn.socket_read_into_ptr(buf_ptr, len)?
r := ws.ssl_conn.socket_read_into_ptr(buf_ptr, len)!
return r
} else {
r := ws.conn.read_ptr(buf_ptr, len)?
r := ws.conn.read_ptr(buf_ptr, len)!
return r
}
}
return none
return error('none')
}
// socket_write writes the provided byte array to the socket
fn (mut ws Client) socket_write(bytes []u8) ?int {
fn (mut ws Client) socket_write(bytes []u8) !int {
lock {
if ws.state == .closed || ws.conn.sock.handle <= 1 {
ws.debug_log('socket_write: Socket allready closed')
@@ -61,25 +61,25 @@ fn (mut ws Client) socket_write(bytes []u8) ?int {
}
// shutdown_socket shuts down the socket properly when connection is closed
fn (mut ws Client) shutdown_socket() ? {
fn (mut ws Client) shutdown_socket() ! {
ws.debug_log('shutting down socket')
if ws.is_ssl {
ws.ssl_conn.shutdown()?
ws.ssl_conn.shutdown()!
} else {
ws.conn.close()?
ws.conn.close()!
}
}
// dial_socket connects tcp socket and initializes default configurations
fn (mut ws Client) dial_socket() ?&net.TcpConn {
fn (mut ws Client) dial_socket() !&net.TcpConn {
tcp_address := '$ws.uri.hostname:$ws.uri.port'
mut t := net.dial_tcp(tcp_address)?
mut t := net.dial_tcp(tcp_address)!
optval := int(1)
t.sock.set_option_int(.keep_alive, optval)?
t.sock.set_option_int(.keep_alive, optval)!
t.set_read_timeout(ws.read_timeout)
t.set_write_timeout(ws.write_timeout)
if ws.is_ssl {
ws.ssl_conn.connect(mut t, ws.uri.hostname)?
ws.ssl_conn.connect(mut t, ws.uri.hostname)!
}
return t
}

View File

@@ -37,35 +37,35 @@ const (
)
// validate_client validates client frame rules from RFC6455
pub fn (mut ws Client) validate_frame(frame &Frame) ? {
pub fn (mut ws Client) validate_frame(frame &Frame) ! {
if frame.rsv1 || frame.rsv2 || frame.rsv3 {
ws.close(1002, 'rsv cannot be other than 0, not negotiated')?
ws.close(1002, 'rsv cannot be other than 0, not negotiated')!
return error('rsv cannot be other than 0, not negotiated')
}
if (int(frame.opcode) >= 3 && int(frame.opcode) <= 7)
|| (int(frame.opcode) >= 11 && int(frame.opcode) <= 15) {
ws.close(1002, 'use of reserved opcode')?
ws.close(1002, 'use of reserved opcode')!
return error('use of reserved opcode')
}
if frame.has_mask && !ws.is_server {
// server should never send masked frames
// to client, close connection
ws.close(1002, 'client got masked frame')?
ws.close(1002, 'client got masked frame')!
return error('client sent masked frame')
}
if is_control_frame(frame.opcode) {
if !frame.fin {
ws.close(1002, 'control message must not be fragmented')?
ws.close(1002, 'control message must not be fragmented')!
return error('unexpected control frame with no fin')
}
if frame.payload_len > 125 {
ws.close(1002, 'control frames must not exceed 125 bytes')?
ws.close(1002, 'control frames must not exceed 125 bytes')!
return error('unexpected control frame payload length')
}
}
if frame.fin == false && ws.fragments.len == 0 && frame.opcode == .continuation {
err_msg := 'unexecpected continuation, there are no frames to continue, $frame'
ws.close(1002, err_msg)?
ws.close(1002, err_msg)!
return error(err_msg)
}
}
@@ -81,7 +81,7 @@ fn is_data_frame(opcode OPCode) bool {
}
// read_payload reads the message payload from the socket
fn (mut ws Client) read_payload(frame &Frame) ?[]u8 {
fn (mut ws Client) read_payload(frame &Frame) ![]u8 {
if frame.payload_len == 0 {
return []u8{}
}
@@ -89,7 +89,7 @@ fn (mut ws Client) read_payload(frame &Frame) ?[]u8 {
mut read_buf := [1]u8{}
mut bytes_read := 0
for bytes_read < frame.payload_len {
len := ws.socket_read_ptr(&read_buf[0], 1)?
len := ws.socket_read_ptr(&read_buf[0], 1)!
if len != 1 {
return error('expected read all message, got zero')
}
@@ -109,21 +109,21 @@ fn (mut ws Client) read_payload(frame &Frame) ?[]u8 {
// validate_utf_8 validates payload for valid utf8 encoding
// - Future implementation needs to support fail fast utf errors for strict autobahn conformance
fn (mut ws Client) validate_utf_8(opcode OPCode, payload []u8) ? {
fn (mut ws Client) validate_utf_8(opcode OPCode, payload []u8) ! {
if opcode in [.text_frame, .close] && !utf8.validate(payload.data, payload.len) {
ws.logger.error('malformed utf8 payload, payload len: ($payload.len)')
ws.send_error_event('Recieved malformed utf8.')
ws.close(1007, 'malformed utf8 payload')?
ws.close(1007, 'malformed utf8 payload')!
return error('malformed utf8 payload')
}
}
// read_next_message reads 1 to n frames to compose a message
pub fn (mut ws Client) read_next_message() ?Message {
pub fn (mut ws Client) read_next_message() !Message {
for {
frame := ws.parse_frame_header()?
ws.validate_frame(&frame)?
frame_payload := ws.read_payload(&frame)?
frame := ws.parse_frame_header()!
ws.validate_frame(&frame)!
frame_payload := ws.read_payload(&frame)!
if is_control_frame(frame.opcode) {
// Control frames can interject other frames
// and need to be returned immediately
@@ -161,12 +161,12 @@ pub fn (mut ws Client) read_next_message() ?Message {
ws.fragments = []
}
if is_data_frame(frame.opcode) {
ws.close(0, '')?
ws.close(0, '')!
return error('Unexpected frame opcode')
}
payload := ws.payload_from_fragments(frame_payload)?
payload := ws.payload_from_fragments(frame_payload)!
opcode := ws.opcode_from_fragments()
ws.validate_utf_8(opcode, payload)?
ws.validate_utf_8(opcode, payload)!
msg := Message{
opcode: opcode
payload: payload.clone()
@@ -177,11 +177,11 @@ pub fn (mut ws Client) read_next_message() ?Message {
}
return msg
}
return none
return error('none')
}
// payload_from_fragments returs the whole paylaod from fragmented message
fn (ws Client) payload_from_fragments(fin_payload []u8) ?[]u8 {
fn (ws Client) payload_from_fragments(fin_payload []u8) ![]u8 {
mut total_size := 0
for f in ws.fragments {
if f.data.len > 0 {
@@ -208,14 +208,14 @@ fn (ws Client) opcode_from_fragments() OPCode {
}
// parse_frame_header parses next message by decoding the incoming frames
pub fn (mut ws Client) parse_frame_header() ?Frame {
pub fn (mut ws Client) parse_frame_header() !Frame {
mut buffer := [256]u8{}
mut bytes_read := 0
mut frame := Frame{}
mut rbuff := [1]u8{}
mut mask_end_byte := 0
for ws.state == .open {
read_bytes := ws.socket_read_ptr(&rbuff[0], 1)?
read_bytes := ws.socket_read_ptr(&rbuff[0], 1)!
if read_bytes == 0 {
// this is probably a timeout or close
continue

View File

@@ -10,20 +10,20 @@ fn main() {
}
// update the reports
uri := 'ws://autobahn_server:9001/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
mut ws := websocket.new_client(uri)!
ws.connect()!
ws.listen()!
}
fn handle_case(case_nr int) ? {
fn handle_case(case_nr int) ! {
uri := 'ws://autobahn_server:9001/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
mut ws := websocket.new_client(uri)!
ws.on_message(on_message)
ws.connect()?
ws.listen()?
ws.connect()!
ws.listen()!
}
fn on_message(mut ws websocket.Client, msg &websocket.Message) ? {
fn on_message(mut ws websocket.Client, msg &websocket.Message) ! {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn

View File

@@ -11,21 +11,21 @@ fn main() {
// update the reports
// uri := 'wss://localhost:9002/updateReports?agent=v-client'
uri := 'wss://autobahn_server_wss:9002/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
mut ws := websocket.new_client(uri)!
ws.connect()!
ws.listen()!
}
fn handle_case(case_nr int) ? {
fn handle_case(case_nr int) ! {
uri := 'wss://autobahn_server_wss:9002/runCase?case=$case_nr&agent=v-client'
// uri := 'wss://localhost:9002/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
mut ws := websocket.new_client(uri)!
ws.on_message(on_message)
ws.connect()?
ws.listen()?
ws.connect()!
ws.listen()!
}
fn on_message(mut ws websocket.Client, msg &websocket.Message) ? {
fn on_message(mut ws websocket.Client, msg &websocket.Message) ! {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn

View File

@@ -9,15 +9,15 @@ fn main() {
s.listen() or { panic(err) }
}
fn handle_case(case_nr int) ? {
fn handle_case(case_nr int) ! {
uri := 'ws://localhost:9002/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
mut ws := websocket.new_client(uri)!
ws.on_message(on_message)
ws.connect()?
ws.listen()?
ws.connect()!
ws.listen()!
}
fn on_message(mut ws websocket.Client, msg &websocket.Message) ? {
fn on_message(mut ws websocket.Client, msg &websocket.Message) ! {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn

View File

@@ -10,20 +10,20 @@ fn main() {
}
// update the reports
uri := 'ws://localhost:9001/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
mut ws := websocket.new_client(uri)!
ws.connect()!
ws.listen()!
}
fn handle_case(case_nr int) ? {
fn handle_case(case_nr int) ! {
uri := 'ws://localhost:9001/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
mut ws := websocket.new_client(uri)!
ws.on_message(on_message)
ws.connect()?
ws.listen()?
ws.connect()!
ws.listen()!
}
fn on_message(mut ws websocket.Client, msg &websocket.Message) ? {
fn on_message(mut ws websocket.Client, msg &websocket.Message) ! {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn

View File

@@ -11,21 +11,21 @@ fn main() {
// update the reports
// uri := 'wss://localhost:9002/updateReports?agent=v-client'
uri := 'wss://autobahn_server_wss:9002/updateReports?agent=v-client'
mut ws := websocket.new_client(uri)?
ws.connect()?
ws.listen()?
mut ws := websocket.new_client(uri)!
ws.connect()!
ws.listen()!
}
fn handle_case(case_nr int) ? {
fn handle_case(case_nr int) ! {
uri := 'wss://autobahn_server_wss:9002/runCase?case=$case_nr&agent=v-client'
// uri := 'wss://localhost:9002/runCase?case=$case_nr&agent=v-client'
mut ws := websocket.new_client(uri)?
mut ws := websocket.new_client(uri)!
ws.on_message(on_message)
ws.connect()?
ws.listen()?
ws.connect()!
ws.listen()!
}
fn on_message(mut ws websocket.Client, msg &websocket.Message) ? {
fn on_message(mut ws websocket.Client, msg &websocket.Message) ! {
// autobahn tests expects to send same message back
if msg.opcode == .pong {
// We just wanna pass text and binary message back to autobahn

View File

@@ -27,7 +27,7 @@ fn create_masking_key() []u8 {
}
// create_key_challenge_response creates a key challange response from security key
fn create_key_challenge_response(seckey string) ?string {
fn create_key_challenge_response(seckey string) !string {
if seckey.len == 0 {
return error('unexpected seckey lengt zero')
}

View File

@@ -88,12 +88,12 @@ pub struct ClientOpt {
}
// new_client instance a new websocket client
pub fn new_client(address string, opt ClientOpt) ?&Client {
uri := parse_uri(address)?
pub fn new_client(address string, opt ClientOpt) !&Client {
uri := parse_uri(address)!
return &Client{
conn: 0
is_server: false
ssl_conn: ssl.new_ssl_conn()?
ssl_conn: ssl.new_ssl_conn()!
is_ssl: address.starts_with('wss')
logger: opt.logger
uri: uri
@@ -106,19 +106,19 @@ pub fn new_client(address string, opt ClientOpt) ?&Client {
}
// connect connects to remote websocket server
pub fn (mut ws Client) connect() ? {
ws.assert_not_connected()?
pub fn (mut ws Client) connect() ! {
ws.assert_not_connected()!
ws.set_state(.connecting)
ws.logger.info('connecting to host $ws.uri')
ws.conn = ws.dial_socket()?
ws.handshake()?
ws.conn = ws.dial_socket()!
ws.handshake()!
ws.set_state(.open)
ws.logger.info('successfully connected to host $ws.uri')
ws.send_open_event()
}
// listen listens and processes incoming messages
pub fn (mut ws Client) listen() ? {
pub fn (mut ws Client) listen() ! {
mut log := 'Starting client listener, server($ws.is_server)...'
ws.logger.info(log)
unsafe { log.free() }
@@ -185,30 +185,30 @@ pub fn (mut ws Client) listen() ? {
}
if msg.payload.len > 0 {
if msg.payload.len == 1 {
ws.close(1002, 'close payload cannot be 1 byte')?
ws.close(1002, 'close payload cannot be 1 byte')!
return error('close payload cannot be 1 byte')
}
code := u16(msg.payload[0]) << 8 | u16(msg.payload[1])
if code in invalid_close_codes {
ws.close(1002, 'invalid close code: $code')?
ws.close(1002, 'invalid close code: $code')!
return error('invalid close code: $code')
}
reason := if msg.payload.len > 2 { msg.payload[2..] } else { []u8{} }
if reason.len > 0 {
ws.validate_utf_8(.close, reason)?
ws.validate_utf_8(.close, reason)!
}
if ws.state !in [.closing, .closed] {
// sending close back according to spec
ws.debug_log('close with reason, code: $code, reason: $reason')
r := reason.bytestr()
ws.close(code, r)?
ws.close(code, r)!
}
unsafe { msg.free() }
} else {
if ws.state !in [.closing, .closed] {
ws.debug_log('close with reason, no code')
// sending close back according to spec
ws.close(1000, 'normal')?
ws.close(1000, 'normal')!
}
unsafe { msg.free() }
}
@@ -217,7 +217,7 @@ pub fn (mut ws Client) listen() ? {
.continuation {
ws.logger.error('unexpected opcode continuation, nothing to continue')
ws.send_error_event('unexpected opcode continuation, nothing to continue')
ws.close(1002, 'nothing to continue')?
ws.close(1002, 'nothing to continue')!
return error('unexpected opcode continuation, nothing to continue')
}
}
@@ -230,17 +230,17 @@ fn (mut ws Client) manage_clean_close() {
}
// ping sends ping message to server
pub fn (mut ws Client) ping() ? {
ws.send_control_frame(.ping, 'PING', [])?
pub fn (mut ws Client) ping() ! {
ws.send_control_frame(.ping, 'PING', [])!
}
// pong sends pong message to server,
pub fn (mut ws Client) pong() ? {
ws.send_control_frame(.pong, 'PONG', [])?
pub fn (mut ws Client) pong() ! {
ws.send_control_frame(.pong, 'PONG', [])!
}
// write_ptr writes len bytes provided a byteptr with a websocket messagetype
pub fn (mut ws Client) write_ptr(bytes &u8, payload_len int, code OPCode) ?int {
pub fn (mut ws Client) write_ptr(bytes &u8, payload_len int, code OPCode) !int {
// ws.debug_log('write_ptr code: $code')
if ws.state != .open || ws.conn.sock.handle < 1 {
// todo: send error here later
@@ -290,7 +290,7 @@ pub fn (mut ws Client) write_ptr(bytes &u8, payload_len int, code OPCode) ?int {
header[12] = masking_key[2]
header[13] = masking_key[3]
} else {
ws.close(1009, 'frame too large')?
ws.close(1009, 'frame too large')!
return error('frame too large')
}
}
@@ -307,7 +307,7 @@ pub fn (mut ws Client) write_ptr(bytes &u8, payload_len int, code OPCode) ?int {
frame_buf[header_len + i] ^= masking_key[i % 4] & 0xff
}
}
written_len := ws.socket_write(frame_buf)?
written_len := ws.socket_write(frame_buf)!
unsafe {
frame_buf.free()
masking_key.free()
@@ -317,17 +317,17 @@ pub fn (mut ws Client) write_ptr(bytes &u8, payload_len int, code OPCode) ?int {
}
// write writes a byte array with a websocket messagetype to socket
pub fn (mut ws Client) write(bytes []u8, code OPCode) ?int {
pub fn (mut ws Client) write(bytes []u8, code OPCode) !int {
return ws.write_ptr(&u8(bytes.data), bytes.len, code)
}
// write_str, writes a string with a websocket texttype to socket
pub fn (mut ws Client) write_string(str string) ?int {
pub fn (mut ws Client) write_string(str string) !int {
return ws.write_ptr(str.str, str.len, .text_frame)
}
// close closes the websocket connection
pub fn (mut ws Client) close(code int, message string) ? {
pub fn (mut ws Client) close(code int, message string) ! {
ws.debug_log('sending close, $code, $message')
if ws.state in [.closed, .closing] || ws.conn.sock.handle <= 1 {
ws.debug_log('close: Websocket allready closed ($ws.state), $message, $code handle($ws.conn.sock.handle)')
@@ -350,16 +350,16 @@ pub fn (mut ws Client) close(code int, message string) ? {
for i in 0 .. message.len {
close_frame[i + 2] = message[i]
}
ws.send_control_frame(.close, 'CLOSE', close_frame)?
ws.send_control_frame(.close, 'CLOSE', close_frame)!
unsafe { close_frame.free() }
} else {
ws.send_control_frame(.close, 'CLOSE', [])?
ws.send_control_frame(.close, 'CLOSE', [])!
}
ws.fragments = []
}
// send_control_frame sends a control frame to the server
fn (mut ws Client) send_control_frame(code OPCode, frame_typ string, payload []u8) ? {
fn (mut ws Client) send_control_frame(code OPCode, frame_typ string, payload []u8) ! {
ws.debug_log('send control frame $code, frame_type: $frame_typ')
if ws.state !in [.open, .closing] && ws.conn.sock.handle > 1 {
return error('socket is not connected')
@@ -419,8 +419,8 @@ fn (mut ws Client) send_control_frame(code OPCode, frame_typ string, payload []u
}
// parse_uri parses the url to a Uri
fn parse_uri(url string) ?&Uri {
u := urllib.parse(url)?
fn parse_uri(url string) !&Uri {
u := urllib.parse(url)!
request_uri := u.request_uri()
v := request_uri.split('?')
mut port := u.port()
@@ -452,7 +452,7 @@ fn (mut ws Client) set_state(state State) {
}
// assert_not_connected returns error if the connection is not connected
fn (ws Client) assert_not_connected() ? {
fn (ws Client) assert_not_connected() ! {
match ws.state {
.connecting { return error('connect: websocket is connecting') }
.open { return error('connect: websocket already open') }
@@ -462,10 +462,10 @@ fn (ws Client) assert_not_connected() ? {
}
// reset_state resets the websocket and initialize default settings
fn (mut ws Client) reset_state() ? {
fn (mut ws Client) reset_state() ! {
lock {
ws.state = .closed
ws.ssl_conn = ssl.new_ssl_conn()?
ws.ssl_conn = ssl.new_ssl_conn()!
ws.flags = []
ws.fragments = []
}

View File

@@ -60,9 +60,9 @@ pub fn (mut s Server) set_ping_interval(seconds int) {
}
// listen start listen and process to incoming connections from websocket clients
pub fn (mut s Server) listen() ? {
pub fn (mut s Server) listen() ! {
s.logger.info('websocket server: start listen on port $s.port')
s.ls = net.listen_tcp(s.family, ':$s.port')?
s.ls = net.listen_tcp(s.family, ':$s.port')!
s.set_state(.open)
go s.handle_ping()
for {
@@ -110,20 +110,20 @@ fn (mut s Server) handle_ping() {
}
// serve_client accepts incoming connection and sets up the callbacks
fn (mut s Server) serve_client(mut c Client) ? {
fn (mut s Server) serve_client(mut c Client) ! {
c.logger.debug('server-> Start serve client ($c.id)')
defer {
c.logger.debug('server-> End serve client ($c.id)')
}
mut handshake_response, mut server_client := s.handle_server_handshake(mut c)?
accept := s.send_connect_event(mut server_client)?
mut handshake_response, mut server_client := s.handle_server_handshake(mut c)!
accept := s.send_connect_event(mut server_client)!
if !accept {
s.logger.debug('server-> client not accepted')
c.shutdown_socket()?
c.shutdown_socket()!
return
}
// the client is accepted
c.socket_write(handshake_response.bytes())?
c.socket_write(handshake_response.bytes())!
lock {
s.clients[server_client.client.id] = server_client
}
@@ -155,7 +155,7 @@ fn (mut s Server) setup_callbacks(mut sc ServerClient) {
}
}
// set standard close so we can remove client if closed
sc.client.on_close_ref(fn (mut c Client, code int, reason string, mut sc ServerClient) ? {
sc.client.on_close_ref(fn (mut c Client, code int, reason string, mut sc ServerClient) ! {
c.logger.debug('server-> Delete client')
lock {
sc.server.clients.delete(sc.client.id)
@@ -164,12 +164,12 @@ fn (mut s Server) setup_callbacks(mut sc ServerClient) {
}
// accept_new_client creates a new client instance for client that connects to the socket
fn (mut s Server) accept_new_client() ?&Client {
mut new_conn := s.ls.accept()?
fn (mut s Server) accept_new_client() !&Client {
mut new_conn := s.ls.accept()!
c := &Client{
is_server: true
conn: new_conn
ssl_conn: ssl.new_ssl_conn()?
ssl_conn: ssl.new_ssl_conn()!
logger: s.logger
state: .open
last_pong_ut: time.now().unix

View File

@@ -50,12 +50,12 @@ fn test_ws_ipv4() {
}
}
fn start_server(family net.AddrFamily, listen_port int) ? {
fn start_server(family net.AddrFamily, listen_port int) ! {
mut s := websocket.new_server(family, listen_port, '')
// make that in execution test time give time to execute at least one time
s.ping_interval = 1
s.on_connect(fn (mut s websocket.ServerClient) ?bool {
s.on_connect(fn (mut s websocket.ServerClient) !bool {
// here you can look att the client info and accept or not accept
// just returning a true/false
if s.resource_name != '/' {
@@ -63,37 +63,37 @@ fn start_server(family net.AddrFamily, listen_port int) ? {
return false
}
return true
})?
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
})!
s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ! {
match msg.opcode {
.pong { ws.write_string('pong')? }
else { ws.write(msg.payload, msg.opcode)? }
.pong { ws.write_string('pong')! }
else { ws.write(msg.payload, msg.opcode)! }
}
})
s.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
s.on_close(fn (mut ws websocket.Client, code int, reason string) ! {
// not used
})
s.listen() or { panic('websocket server could not listen, err: $err') }
}
// ws_test tests connect to the websocket server from websocket client
fn ws_test(family net.AddrFamily, uri string) ? {
fn ws_test(family net.AddrFamily, uri string) ! {
eprintln('connecting to $uri ...')
mut test_results := WebsocketTestResults{}
mut ws := websocket.new_client(uri)?
ws.on_open(fn (mut ws websocket.Client) ? {
ws.pong()?
mut ws := websocket.new_client(uri)!
ws.on_open(fn (mut ws websocket.Client) ! {
ws.pong()!
assert true
})
ws.on_error(fn (mut ws websocket.Client, err string) ? {
ws.on_error(fn (mut ws websocket.Client, err string) ! {
println('error: $err')
// this can be thrown by internet connection problems
assert false
})
ws.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, mut res WebsocketTestResults) ? {
ws.on_message_ref(fn (mut ws websocket.Client, msg &websocket.Message, mut res WebsocketTestResults) ! {
println('client got type: $msg.opcode payload:\n$msg.payload')
if msg.opcode == .text_frame {
smessage := msg.payload.bytestr()