aboutsummaryrefslogtreecommitdiff
path: root/lib/MasterServer/Database/Pg/dbBeacon.pm
blob: e396810ff5e93d5230f1b3ca3bcd557f721078ae (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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151

package MasterServer::Database::Pg::dbBeacon;

use strict;
use warnings;
use Exporter 'import';

our @EXPORT = qw| add_beacon
                  remove_pending 
                  set_direct_beacon 
                  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   = TRUE
      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;
}

##  server checks out, remove entry from the pending list.
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("deleted", "removed pending id $id from the list of pending servers") if ($u > 0);
  
  # it was added to pending
  return 2 if ($u > 0);
  
  # or else report error
  $self->log("error", "an error occurred deleting server $id from the pending list");
  return -1;
}


## mark server as "direct beacon to this masterserver"
sub set_direct_beacon {
  my ($self, $ip, $port) = @_;
  
  # update or add server to serverlist
  my $u = $self->{dbh}->do("UPDATE serverlist 
                            SET b333ms   = TRUE
                            WHERE ip = ? 
                            AND port = ?",
                            undef, $ip, $port);

  # notify
  $self->log("update", "$ip:$port is a direct beacon.") if ($u > 0);
  
  # if found, updated; done
  return 0 if ($u > 0);
  
  # or else report error
  $self->log("error", "an error occurred setting server $ip:$port as direct beacon");
  return -1;
}



##   Get pending server by ip, beacon port.
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];
}

##   Same as get_pending_beacon, but with heartbeat port as identifier
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.
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 SECONDS')
             AND id > ?
             ORDER BY id ASC LIMIT 1", undef, $id)->[0];
}


1;