]> WPIA git - gigi.git/blob - src/club/wpia/gigi/ping/PingerDaemon.java
pre: document intendet ping behaviour
[gigi.git] / src / club / wpia / gigi / ping / PingerDaemon.java
1 package club.wpia.gigi.ping;
2
3 import java.security.KeyStore;
4 import java.util.HashMap;
5 import java.util.LinkedList;
6 import java.util.Queue;
7
8 import club.wpia.gigi.database.DatabaseConnection;
9 import club.wpia.gigi.database.DatabaseConnection.Link;
10 import club.wpia.gigi.database.GigiPreparedStatement;
11 import club.wpia.gigi.database.GigiResultSet;
12 import club.wpia.gigi.dbObjects.Certificate.RevocationType;
13 import club.wpia.gigi.dbObjects.Domain;
14 import club.wpia.gigi.dbObjects.DomainPingConfiguration;
15 import club.wpia.gigi.dbObjects.DomainPingType;
16 import club.wpia.gigi.util.RandomToken;
17
18 /**
19  * <p>
20  * This thread is executing pings for domains, if the last ping is older than a
21  * specific amount of time.
22  * </p>
23  * <p>
24  * When a ping fails the corresponding domain becomes unverified. If the ping
25  * succeeds the domains becomes verified and all other domain with the same name
26  * become unverified.
27  * </p>
28  * <p>
29  * When a domain becomes unverified and has still certificated attached to it
30  * the certificates will become "pending for revocation". This state is removed
31  * when the domain is successfully verified again. When this state prolongs for
32  * more than 2 weeks, such certificates are revoked with type
33  * {@link RevocationType#PING_TIMEOUT}.
34  * </p>
35  */
36 public class PingerDaemon extends Thread {
37
38     HashMap<DomainPingType, DomainPinger> pingers = new HashMap<>();
39
40     private KeyStore truststore;
41
42     private Queue<DomainPingConfiguration> toExecute = new LinkedList<>();
43
44     public PingerDaemon(KeyStore truststore) {
45         this.truststore = truststore;
46     }
47
48     @Override
49     public void run() {
50         try (Link l = DatabaseConnection.newLink(false)) {
51             runWithConnection();
52         } catch (InterruptedException e) {
53             e.printStackTrace();
54         }
55     }
56
57     public void runWithConnection() {
58
59         pingers.put(DomainPingType.EMAIL, new EmailPinger());
60         pingers.put(DomainPingType.SSL, new SSLPinger(truststore));
61         pingers.put(DomainPingType.HTTP, new HTTPFetch());
62         pingers.put(DomainPingType.DNS, new DNSPinger());
63
64         while (true) {
65             try {
66                 boolean worked = false;
67                 synchronized (this) {
68                     DomainPingConfiguration conf;
69                     while ((conf = toExecute.peek()) != null) {
70                         worked = true;
71                         handle(conf);
72                         toExecute.remove();
73                     }
74                     notifyAll();
75                 }
76                 try (GigiPreparedStatement searchNeededPings = new GigiPreparedStatement("SELECT `pc`.`id`" //
77                         + " FROM `pingconfig` AS `pc`" //
78                         + " INNER JOIN `domains` AS `d` ON `d`.`id` = `pc`.`domainid`" //
79                         + " WHERE `d`.`deleted` IS NULL" //
80                         + "  AND `pc`.`deleted` IS NULL" //
81                         + "  AND NOT EXISTS (" //
82                         + "    SELECT 1 FROM `domainPinglog` AS `dpl`" //
83                         + "    WHERE `dpl`.`configId` = `pc`.`id`" //
84                         + "     AND `dpl`.`when` >= CURRENT_TIMESTAMP - interval '6 mons')")) {
85
86                     GigiResultSet rs = searchNeededPings.executeQuery();
87                     while (rs.next()) {
88                         worked = true;
89                         handle(DomainPingConfiguration.getById(rs.getInt("id")));
90                     }
91                 }
92                 try {
93                     if ( !worked) {
94                         Thread.sleep(5000);
95                     }
96                 } catch (InterruptedException e) {
97                 }
98             } catch (Throwable t) {
99                 t.printStackTrace();
100                 try {
101                     Thread.sleep(5000);
102                 } catch (InterruptedException e) {
103                 }
104             }
105         }
106     }
107
108     private void handle(DomainPingConfiguration conf) {
109         DomainPingType type = conf.getType();
110         String config = conf.getInfo();
111         DomainPinger dp = pingers.get(type);
112         if (dp != null) {
113             if (dp instanceof EmailPinger) {
114                 String token = null;
115                 token = RandomToken.generateToken(16);
116                 config = config + ":" + token;
117             }
118             Domain target = conf.getTarget();
119             System.err.println("Executing " + dp + " on " + target + " (" + System.currentTimeMillis() + ")");
120             try {
121                 dp.ping(target, config, target.getOwner(), conf.getId());
122             } catch (Throwable t) {
123                 t.printStackTrace();
124                 DomainPinger.enterPingResult(conf.getId(), "error", "exception", null);
125             }
126             System.err.println("done (" + System.currentTimeMillis() + ")");
127         }
128     }
129
130     public synchronized void queue(DomainPingConfiguration toReping) {
131         interrupt();
132         toExecute.add(toReping);
133         while (toExecute.size() > 0) {
134             try {
135                 wait();
136             } catch (InterruptedException e) {
137                 e.printStackTrace();
138             }
139         }
140     }
141 }