summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorheav <hheav3@gmail.com>2022-11-15 00:47:30 +0000
committerheav <hheav3@gmail.com>2022-11-15 00:47:30 +0000
commit2b9763237e45737dc75feb27cacd12be8f78e64c (patch)
tree9d917eb44a07ca90a7b724444dde0c4fc17c5315
parentdc04bd10cec0618b7d7632cde07405ee5c77bf89 (diff)
added lots of features
-rw-r--r--main.lua48
-rw-r--r--server_logic.lua128
2 files changed, 173 insertions, 3 deletions
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