From 2b9763237e45737dc75feb27cacd12be8f78e64c Mon Sep 17 00:00:00 2001 From: heav Date: Tue, 15 Nov 2022 00:47:30 +0000 Subject: added lots of features --- main.lua | 48 +++++++++++++++++++-- server_logic.lua | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 server_logic.lua diff --git a/main.lua b/main.lua index cf03428..a1614ea 100644 --- a/main.lua +++ b/main.lua @@ -7,9 +7,12 @@ local httpserver = require("http.server") local websocket = require("http.websocket") local headers = require "http.headers" +local logic = require("server_logic") + function onstream(server, stream) print("stream you.") - local ws = websocket.new_from_stream(stream, stream:get_headers()) + local head = stream:get_headers() + local ws = websocket.new_from_stream(stream, head) if not ws then local response = headers.new() response:append(":status", "400") @@ -17,11 +20,50 @@ function onstream(server, stream) stream:write_chunk("bad request: not a websocket handshake", true) return end + + local path = head:get(":path") + if not path:sub(1,6) == "/room/" or #path < 7 then + local response = headers.new() + response:append(":status", "404") + stream:write_headers(response, false) + stream:write_chunk("please access /room/(roomname).", true) + return + end + local room = path:sub(7,#path) + ws:accept() + logic.onsocket(ws,room) + + local ws_open = true + function close() + logic.onclose(ws) + if ws_open then ws:close() end + ws_open = false + + end + + cq:wrap(function() + while true do + logic.ping(ws) + cqueues.sleep(logic.ping_interval) + if not ws_open then break end + if os.time() - logic.last_ping(ws) >= 18 then + close() + return + end + end + end) + while true do + if not ws_open then + return + end local data = ws:receive() - if not data then return end - ws:send(data) + if not data or not ws_open then + close() + return + end + logic.onmessage(ws, data) end end diff --git a/server_logic.lua b/server_logic.lua new file mode 100644 index 0000000..4937351 --- /dev/null +++ b/server_logic.lua @@ -0,0 +1,128 @@ +local M = {} +local clients = {} +local socket_client_mapping = {} +local activerooms = {} + +local ping_interval = 6 +M.ping_interval = ping_interval +local debug_mode = true + +function debug(...) + if debug_mode then print(...) end +end + +local json = require("dkjson") +local db = require("messagelog") + +local room_metatable = { + __index = { + join = function(self, client) + self.users[client] = 1 + debug("client joined &"..self.name) + end, + leave = function(self, client) + self.users[client] = nil + debug("client left &"..self.name) + end, + } +} + +local client_metatable = { + __index = { + onmessage = function(self, m) + local msg = json.decode(m) + debug("client sent message ",m) + if not msg or not type(msg.data) == "table" or not type(msg.type) == "string" then + return + end + local data = msg.data + if msg.type == "ping" then + self:reply(msg, { + data = { + time = msg.data.time + } + }) + if not self.joined then + self.joined = true + activerooms[self.room]:join(self) + end + end + end, + disconnect = function(self) + if self.joined then + activerooms[self.room]:leave(self) + end + clients[self] = nil + end, + send_event = function(self, tbl) + local s = json.encode(tbl) + self.s:send(s) + end, + reply = function(self, original, reply) + reply.id = original.id + reply.type = original.type .. "-reply" + local s = json.encode(reply) + self.s:send(s) + end, + ping = function(self) + self:send_event { + type = "ping-event", + data = { + time = os.time(), + next = os.time() + 6, + } + } + end, + } +} + +function try_room(r) + if activerooms[r] then return activerooms[r] end + local res = { + users = {}, + name = r, + } + setmetatable(res, room_metatable) + activerooms[r] = res + return res +end + +function M.getclient(s) + return socket_client_mapping[s] +end + +function M.onsocket(s, room) + local client = { + s = s, + room = room, + joined = false, + last_ping_time = os.time(), + } + setmetatable(client,client_metatable) + socket_client_mapping[s] = client + clients[client] = 1 +end + +function M.onclose(s) + local client = M.getclient(s) + if not client then return end + client:disconnect() + socket_client_mapping[s] = nil +end + +function M.onmessage(s,m) + local client = M.getclient(s) + client:onmessage(m) +end + +function M.last_ping(s) + local client = M.getclient(s) + return client.last_ping_time +end + +function M.ping(s) + local client = M.getclient(s) + client:ping() +end + +return M \ No newline at end of file -- cgit v1.2.3