summaryrefslogtreecommitdiff
path: root/server_logic.lua
blob: 4c6c2290117a5cd0f4f3d51b4dedc8d113787aa9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
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
					try(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