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
local 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,
}
}
local 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
|