v2 / examples / veb / websocket / server.v
100 lines · 89 sloc · 2.94 KB · 319eb83525cbfaf18a8518fbe06279c1b6751f1f
Raw
1module main
2
3import os
4import veb
5import log
6import time
7import term
8import net
9import net.http
10import net.websocket
11
12const app_port = 8990
13
14fn main() {
15 log.use_stdout()
16 mut app := &App{
17 wss: new_websocker_server()!
18 }
19 app.mount_static_folder_at(os.resource_abs_path('assets'), '/assets')!
20 app.serve_static('/favicon.ico', os.resource_abs_path('assets/favicon.ico'))!
21 veb.run[App, Context](mut app, app_port)
22}
23
24pub struct Context {
25 veb.Context
26}
27
28pub struct App {
29 veb.StaticHandler
30mut:
31 wss &websocket.Server
32}
33
34pub fn (mut app App) index(mut ctx Context) veb.Result {
35 return $veb.html()
36}
37
38pub fn (mut app App) ws(mut ctx Context) veb.Result {
39 key := ctx.get_header(http.CommonHeader.sec_websocket_key) or { '' }
40 if key == '' {
41 ctx.error('Invalid websocket handshake. Key is missing.')
42 return ctx.redirect('/')
43 }
44 dump(ctx.req.cookie('token') or { http.Cookie{} }.value)
45 wlog('> transferring connection with key: ${key}, to the websocket server ${voidptr(app.wss)} ...')
46 ctx.takeover_conn()
47 ctx.conn.set_write_timeout(time.infinite)
48 ctx.conn.set_read_timeout(time.infinite)
49 spawn fn (mut wss websocket.Server, mut connection net.TcpConn, key string) {
50 wss.handle_handshake(mut connection, key) or { wlog('handle_handshake error: ${err}') }
51 wlog('>> wss.handle_handshake finished, key: ${key}')
52 }(mut app.wss, mut ctx.conn, key)
53 wlog('> done transferring connection')
54 return veb.no_result()
55}
56
57fn slog(message string) {
58 eprintln(term.colorize(term.bright_yellow, message))
59}
60
61fn wlog(message string) {
62 eprintln(term.colorize(term.bright_blue, message))
63}
64
65fn new_websocker_server() !&websocket.Server {
66 mut logger := &log.Log{}
67 logger.set_level(.info)
68 logger.set_output_stream(os.stderr())
69 mut wss := websocket.new_server(.ip, app_port, '', logger: logger)
70 wss.set_ping_interval(100)
71 wss.on_connect(fn [mut logger] (mut server_client websocket.ServerClient) !bool {
72 server_client.client.logger = logger
73 slog('wss.on_connect client.id: ${server_client.client.id} | server_client.client_key: ${server_client.client_key}')
74 return true
75 })!
76 wss.on_close(fn (mut client websocket.Client, code int, reason string) ! {
77 slog('wss.on_close client.id: ${client.id} | code: ${code}, reason: ${reason}')
78 })
79 wss.on_message(fn [mut wss] (mut client websocket.Client, msg &websocket.Message) ! {
80 slog('wss.on_message client.id: ${client.id} | msg.opcode: ${msg.opcode} | msg.payload: `${msg.payload.bytestr()}`')
81 text := '${client.id} says: "${msg.payload.bytestr()}"'
82 // client.write_string(text) or { slog('client.write err: ${err}') return err }
83 for i, _ in rlock wss.server_state {
84 wss.server_state.clients
85 } {
86 mut c := rlock wss.server_state {
87 wss.server_state.clients[i] or { continue }
88 }
89 if c.client.get_state() == .open {
90 c.client.write_string(text) or {
91 slog('error while broadcasting to i: ${i}, ${voidptr(c)}, err: ${err}')
92 continue
93 }
94 }
95 }
96 })
97
98 slog('Websocket Server initialized, wss: ${voidptr(wss)}')
99 return wss
100}
101