summaryrefslogtreecommitdiff
path: root/server.lua
blob: 4ae4c871de9e6ff883c0203a3387cdf7d59df24a (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
local enet = require("enet")
local json = require("json")
local socket = require("socket")
local base64 = require("base64")
local common = require("common")

local server = {}

function server.create(match_addr)
    local srv = {}

    srv.host = enet.host_create()
    srv.secret = common.rand_string(common.secret_len)
    srv.clients = {}

    srv.match = srv.host:connect(match_addr or common.default_match_addr)
    srv.match_req = socket.gettime()

    return srv
end

local function handle_match(srv, pkt)
    if pkt.type == "server_match" then
        if type(pkt.game_id) ~= "string" then
            print("[server] server_match: invalid game_id")
            return
        end

        if srv.game_id then
            print("[server] server_match: received while game already running")
            return
        end

        srv.game_id = pkt.game_id
        srv.invite = base64.encode(srv.game_id .. srv.secret)
    elseif pkt.type == "server_join" then
        if type(pkt.peer_addr) ~= "string" then
            print("[server] server_join: invalid peer_addr")
            return
        end
        srv.host:connect(pkt.peer_addr)
    end
end

local function handle_client(srv, peer, pkt)
    if pkt.type == "server_hi" then
        if type(pkt.secret) ~= "string" then
            print("[server] server_hi: invalid secret")
            return
        end

        if srv.clients[peer] then
            print("[server] server_hi: client already connected")
            return
        end

        if pkt.secret == srv.secret then
            print("[server] auth success " .. tostring(peer))
            srv.clients[peer] = { peer = peer }
            peer:send(json.encode({ type = "client_hi" }))
        else
            print("[server] auth failure " .. tostring(peer))
            peer:send(json.encode({ type = "client_reject" }))
            peer:disconnect()
       end
    end
end

function server.update(srv)
    local event = srv.host:service(20)
    while event do
        if event.type == "receive" then
            local pkt = json.decode(event.data)
            if event.peer == srv.match then
                handle_match(srv, pkt)
            else
                handle_client(srv, event.peer, pkt)
            end
        elseif event.type == "connect" then
            if event.peer == srv.match then
                srv.match:send(json.encode({ type = "match_register" }))
            end
            print("[server] connect " .. tostring(event.peer))
        elseif event.type == "disconnect" then
            print("[server] disconnect " .. tostring(event.peer))
            if event.peer == srv.match then
                -- TODO
            else
                srv.clients[event.peer] = nil
            end
        end
        event = srv.host:service()
    end
end

function server.match_status(srv)
    if srv.game_id then
        return "active", srv.invite
    elseif srv.match_req + 3 >= socket.gettime() then
        return "wait"
    else
        return "fail"
    end
end

function server.close(srv)
    srv.host:destroy()
end

return server