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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
package MasterServer::Database::mysql::dbBeacon;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT = qw| add_beacon
add_pending
remove_pending
get_pending_beacon
get_pending_info
get_next_pending |;
################################################################################
## Update beacon in serverlist or pending list. Add if beacon does not exist in
## either list. Return 0,1,2 if success in adding or -1 on error.
################################################################################
sub add_beacon {
my ($self, $ip, $beaconport, $heartbeat, $gamename, $secure) = @_;
# if address is in list, update the timestamp
my $u = $self->{dbh}->do(
"UPDATE serverlist
SET beacon = NOW(),
updated = NOW(),
gamename = ?,
b333ms = 1
WHERE ip = ?
AND port = ?",
undef, lc $gamename, $ip, $heartbeat);
# notify
$self->log("update", "beacon heartbeat for $ip:$heartbeat") if ($u > 0);
# if serverlist was updated return 0
return 0 if ($u > 0);
# if it is already in the pending list, update it with a new challenge
$u = $self->{dbh}->do(
"UPDATE pending
SET added = NOW(),
beaconport = ?,
gamename = ?,
secure = ?
WHERE ip = ?
AND heartbeat = ?",
undef, $beaconport, lc $gamename, $secure, $ip, $heartbeat);
# notify
$self->log("update", "beacon heartbeat $ip:$beaconport pending $gamename:$heartbeat") if ($u > 0);
# beacon was already in pending list and was updated
return 1 if ($u > 0);
# if not found, add it
$u = $self->{dbh}->do(
"INSERT INTO pending (
ip,
beaconport,
heartbeat,
gamename,
secure)
SELECT ?, ?, ?, ?, ?",
undef, $ip, $beaconport, $heartbeat, lc $gamename, $secure);
# notify
$self->log("add", "beacon heartbeat $ip:$beaconport pending $gamename:$heartbeat") if ($u > 0);
# it was added to pending
return 2 if ($u > 0);
# or else report error
$self->log("error", "an error occurred adding beacon $ip:$beaconport with $gamename:$heartbeat to the pending list");
return -1;
}
################################################################################
## Add an address to the database that was obtained via a method other than
## an udp beacon. Return 0,1,2 if success in adding or -1 on error.
################################################################################
sub add_pending {
my ($self, $ip, $port, $gamename, $secure) = @_;
# if address is in list, update the timestamp
my $u = $self->{dbh}->do(
"UPDATE serverlist
SET updated = NOW()
WHERE ip = ?
AND port = ?",
undef, $ip, $port);
# notify
$self->log("update", "updated serverlist with $ip:$port") if ($u > 0);
# if updated, return 0
return 0 if ($u > 0);
# if it is already in the pending list, update it with a new challenge
$u = $self->{dbh}->do(
"UPDATE pending
SET added = NOW(),
secure = ?
WHERE ip = ?
AND heartbeat = ?",
undef, $secure, $ip, $port);
# notify
$self->log("update", "updated pending with $ip:$port") if ($u > 0);
# return 1 if updated
return 1 if ($u > 0);
# if not found, add it
$u = $self->{dbh}->do(
"INSERT INTO pending (
ip,
heartbeat,
gamename,
secure)
SELECT ?, ?, ?, ?",
undef, $ip, $port, $gamename, $secure);
# notify
$self->log("add", "$ip:$port added pending $gamename") if ($u > 0);
# return 2 if added new
return 2 if ($u > 0);
# else
return -1;
}
################################################################################
## Remove an entry from the pending list. Returns 0 if removed or -1 in case
## of error(s).
################################################################################
sub remove_pending {
my ($self, $id) = @_;
# if address is in list, update the timestamp
my $u = $self->{dbh}->do(
"DELETE FROM pending
WHERE id = ?",
undef, $id);
# notify
$self->log("delete", "removed pending id $id from pending") if ($u > 0);
# it was removed from pending
return 2 if ($u > 0);
# or else report error
$self->log("error", "error deleting server $id from pending");
return -1;
}
################################################################################
## Get pending server by ip, beacon port. Returns * or undef
################################################################################
sub get_pending_beacon {
my ($self, $ip, $port) = @_;
# if address is in list, update the timestamp
return $self->{dbh}->selectall_arrayref(
"SELECT * FROM pending
WHERE ip = ?
AND beaconport = ?",
undef, $ip, $port)->[0];
}
################################################################################
## Get pending server by ip, heartbeat port. Returns * or undef
################################################################################
sub get_pending_info {
my ($self, $ip, $port) = @_;
# if address is in list, update the timestamp
return $self->{dbh}->selectall_arrayref(
"SELECT * FROM pending
WHERE ip = ?
AND heartbeat = ?",
undef, $ip, $port)->[0];
}
################################################################################
## Get server info from any entry with an id higher than the provided one. The
## server is added to pending at least 15 seconds ago. Returns info or undef.
################################################################################
sub get_next_pending {
my ($self, $id) = @_;
# get 1 pending id that is older than 15s
return $self->{dbh}->selectall_arrayref(
"SELECT id, ip, heartbeat, secure FROM pending
WHERE added < NOW() - INTERVAL 15 SECOND
AND id > ?
ORDER BY id ASC LIMIT 1",
undef, $id)->[0];
}
1;
|