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
|
package MasterServer::Database::Pg::dbServerlist;
use strict;
use warnings;
use Exporter 'import';
our @EXPORT = qw| add_to_serverlist
update_serverlist
syncer_add
get_next_server |;
################################################################################
## beacon was verified or otherwise accepted and will now be added to the
## serverlist.
################################################################################
sub add_to_serverlist {
my ($self, $ip, $port, $gamename) = @_;
# update or add server to serverlist
my $u = $self->{dbh}->do("UPDATE serverlist
SET updated = NOW()
WHERE ip = ?
AND port = ?",
undef, $ip, $port);
# notify
$self->log("update", "$ip:$port timestamp updated") if ($u > 0);
# if found, updated; done
return 0 if ($u > 0);
# if not found, add it.
$u = $self->{dbh}->do("INSERT INTO serverlist (ip, port, gamename, country)
SELECT ?, ?, ?, ?",
undef, $ip, $port, $gamename, $self->ip2country($ip));
# notify
$self->log("add", "$ip:$port added to serverlist") if ($u > 0);
# return added
return 1 if ($u > 0);
# or else report error
$self->log("error", "an error occurred adding server $ip:$port ($gamename) to the serverlist");
return -1;
}
################################################################################
## same as add_to_serverlist above, but does not add the server to serverlist
## if it does not exist in serverlist. it must be added by another function
## first.
################################################################################
sub update_serverlist {
my ($self, $ip, $port, $s) = @_;
# update server info
my $u = $self->{dbh}->do(
'UPDATE serverlist
SET updated = NOW(),
gamename = ?,
gamever = ?,
hostname = ?,
hostport = ?
WHERE ip = ?
AND port = ?', undef,
$s->{gamename}, $s->{gamever}, $s->{hostname}, $s->{hostport},
$ip, $port);
# notify
$self->log("update", "server $ip:$port info updated") if ($u > 0);
# return 0 if updated
return 0 if ($u > 0);
# or else report error
$self->log("error", "an error occurred updating server $ip:$port in the serverlist");
return -1;
}
################################################################################
## add new addresses to the pending list, but do not update timestamps. masters
## that sync with each other would otherwise update the timestamp for a server
## which is no longer online.
################################################################################
sub syncer_add {
my ($self, $ip, $port, $gamename, $secure) = @_;
# if address is in list, update the timestamp
my $u = $self->{dbh}->do(
"SELECT * FROM serverlist
WHERE ip = ?
AND port = ?",
undef, $ip, $port);
# notify
$self->log("read","syncer found entry for $ip:$port") if ($u > 0);
# if found, 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 secure = ?
WHERE ip = ?
AND heartbeat = ?",
undef, $secure, $ip, $port);
# notify
$self->log("update","$ip:$port was updated by syncer",
$self->{log_settings}->{db_updated}) if ($u > 0);
# return 1 if found
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","beacon: $ip:$port was added for $gamename after sync") if ($u > 0);
# return 2 if added new
return 2 if ($u > 0);
# or else report error
$self->log("error", "an error occurred adding $ip:$port after sync");
return -1;
}
################################################################################
## get a server address of the next server in line to be queried for game info.
## query must be older than 30 seconds (in case it just got added) and not
## older than 3 hours.
################################################################################
sub get_next_server {
my ($self, $id) = @_;
return $self->{dbh}->selectall_arrayref(
"SELECT id, ip, port FROM serverlist
WHERE added < (NOW() - INTERVAL '15 SECONDS')
AND updated > (NOW() - INTERVAL '3 HOUR')
AND id > ?
AND NOT blacklisted
ORDER BY id ASC LIMIT 1", undef, $id)->[0];
}
1;
|