From: Felix Dörre Date: Sat, 6 Sep 2014 10:59:45 +0000 (+0200) Subject: UPD: Factor out PingConfig objects and pingconfig-form. X-Git-Url: https://code.wpia.club/?p=gigi.git;a=commitdiff_plain;h=76e3ad5851967bea57005ec9858625d4a7071d7c UPD: Factor out PingConfig objects and pingconfig-form. --- diff --git a/src/org/cacert/gigi/Gigi.java b/src/org/cacert/gigi/Gigi.java index bb7c6635..7732f725 100644 --- a/src/org/cacert/gigi/Gigi.java +++ b/src/org/cacert/gigi/Gigi.java @@ -18,6 +18,7 @@ import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.dbObjects.DomainPingConfiguration; import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.output.Form.CSRFException; @@ -333,4 +334,8 @@ public class Gigi extends HttpServlet { instance.pinger.interrupt(); } + public static void requestReping(DomainPingConfiguration dpc) { + instance.pinger.requestReping(dpc); + } + } diff --git a/src/org/cacert/gigi/dbObjects/Domain.java b/src/org/cacert/gigi/dbObjects/Domain.java index 8e575038..b481e76f 100644 --- a/src/org/cacert/gigi/dbObjects/Domain.java +++ b/src/org/cacert/gigi/dbObjects/Domain.java @@ -3,12 +3,58 @@ package org.cacert.gigi.dbObjects; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; import org.cacert.gigi.GigiApiException; import org.cacert.gigi.database.DatabaseConnection; +import org.cacert.gigi.dbObjects.DomainPingConfiguration.PingType; public class Domain implements IdCachable { + public class DomainPingExecution { + + String state; + + String type; + + String info; + + String result; + + DomainPingConfiguration config; + + public DomainPingExecution(ResultSet rs) throws SQLException { + state = rs.getString(1); + type = rs.getString(2); + info = rs.getString(3); + result = rs.getString(4); + config = DomainPingConfiguration.getById(rs.getInt(5)); + } + + public String getState() { + return state; + } + + public String getType() { + return type; + } + + public String getInfo() { + return info; + } + + public String getResult() { + return result; + } + + public DomainPingConfiguration getConfig() { + return config; + } + + } + private User owner; private String suffix; @@ -21,7 +67,7 @@ public class Domain implements IdCachable { ResultSet rs = ps.executeQuery(); if ( !rs.next()) { - throw new IllegalArgumentException("Invalid email id " + id); + throw new IllegalArgumentException("Invalid domain id " + id); } this.id = id; owner = User.getById(rs.getInt(1)); @@ -96,13 +142,37 @@ public class Domain implements IdCachable { return suffix; } - public void addPing(String type, String config) throws GigiApiException { + private LinkedList configs = null; + + public List getConfiguredPings() throws GigiApiException { + LinkedList configs = this.configs; + if (configs == null) { + try { + configs = new LinkedList<>(); + PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id FROM pingconfig WHERE domainid=?"); + ps.setInt(1, id); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + configs.add(DomainPingConfiguration.getById(rs.getInt(1))); + } + rs.close(); + this.configs = configs; + } catch (SQLException e) { + throw new GigiApiException(e); + } + + } + return Collections.unmodifiableList(configs); + } + + public void addPing(PingType ssl, String config) throws GigiApiException { try { PreparedStatement ps = DatabaseConnection.getInstance().prepare("INSERT INTO pingconfig SET domainid=?, type=?, info=?"); ps.setInt(1, id); - ps.setString(2, type); + ps.setString(2, ssl.toString().toLowerCase()); ps.setString(3, config); ps.execute(); + configs = null; } catch (SQLException e) { throw new GigiApiException(e); } @@ -131,18 +201,16 @@ public class Domain implements IdCachable { return false; } - public String[][] getPings() throws GigiApiException { + public DomainPingExecution[] getPings() throws GigiApiException { try { - PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT state, type, info, result FROM domainPinglog INNER JOIN pingconfig ON pingconfig.id=domainPinglog.configid WHERE pingconfig.domainid=? ORDER BY `when` DESC;"); + PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT state, type, info, result, configId FROM domainPinglog INNER JOIN pingconfig ON pingconfig.id=domainPinglog.configid WHERE pingconfig.domainid=? ORDER BY `when` DESC;"); ps.setInt(1, id); ResultSet rs = ps.executeQuery(); rs.last(); - String[][] contents = new String[rs.getRow()][]; + DomainPingExecution[] contents = new DomainPingExecution[rs.getRow()]; rs.beforeFirst(); for (int i = 0; i < contents.length && rs.next(); i++) { - contents[i] = new String[] { - rs.getString(1), rs.getString(2), rs.getString(3), rs.getString(4) - }; + contents[i] = new DomainPingExecution(rs); } return contents; } catch (SQLException e) { diff --git a/src/org/cacert/gigi/dbObjects/DomainPingConfiguration.java b/src/org/cacert/gigi/dbObjects/DomainPingConfiguration.java new file mode 100644 index 00000000..a031b9e4 --- /dev/null +++ b/src/org/cacert/gigi/dbObjects/DomainPingConfiguration.java @@ -0,0 +1,68 @@ +package org.cacert.gigi.dbObjects; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +import org.cacert.gigi.database.DatabaseConnection; + +public class DomainPingConfiguration implements IdCachable { + + public static enum PingType { + EMAIL, DNS, HTTP, SSL; + } + + int id; + + Domain target; + + PingType type; + + String info; + + private DomainPingConfiguration(int id) throws SQLException { + PreparedStatement ps = DatabaseConnection.getInstance().prepare("SELECT id, domainid, type, info FROM pingconfig WHERE id=?"); + ps.setInt(1, id); + + ResultSet rs = ps.executeQuery(); + if ( !rs.next()) { + throw new IllegalArgumentException("Invalid pingconfig id " + id); + } + this.id = rs.getInt("id"); + target = Domain.getById(rs.getInt("domainid")); + type = PingType.valueOf(rs.getString("type").toUpperCase()); + info = rs.getString("info"); + } + + @Override + public int getId() { + return id; + } + + public Domain getTarget() { + return target; + } + + public PingType getType() { + return type; + } + + public String getInfo() { + return info; + } + + private static ObjectCache cache = new ObjectCache<>(); + + public static DomainPingConfiguration getById(int id) { + DomainPingConfiguration res = cache.get(id); + if (res == null) { + try { + cache.put(res = new DomainPingConfiguration(id)); + } catch (SQLException e) { + throw new IllegalArgumentException(e); + } + } + return res; + } + +} diff --git a/src/org/cacert/gigi/output/Form.java b/src/org/cacert/gigi/output/Form.java index a6374e53..7cad69e7 100644 --- a/src/org/cacert/gigi/output/Form.java +++ b/src/org/cacert/gigi/output/Form.java @@ -8,6 +8,7 @@ import javax.servlet.ServletRequest; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; +import org.cacert.gigi.GigiApiException; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.pages.Page; import org.cacert.gigi.util.RandomToken; @@ -25,7 +26,7 @@ public abstract class Form implements Outputable { } - public abstract boolean submit(PrintWriter out, HttpServletRequest req); + public abstract boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException; protected String getCsrfFieldName() { return CSRF_FIELD; diff --git a/src/org/cacert/gigi/pages/account/DomainAddForm.java b/src/org/cacert/gigi/pages/account/DomainAddForm.java index 65e168c4..b220dca3 100644 --- a/src/org/cacert/gigi/pages/account/DomainAddForm.java +++ b/src/org/cacert/gigi/pages/account/DomainAddForm.java @@ -1,24 +1,18 @@ package org.cacert.gigi.pages.account; import java.io.PrintWriter; -import java.util.Arrays; -import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; -import org.cacert.gigi.Gigi; import org.cacert.gigi.GigiApiException; import org.cacert.gigi.dbObjects.Domain; import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.output.Form; -import org.cacert.gigi.output.template.IterableDataset; -import org.cacert.gigi.output.template.OutputableArrayIterable; +import org.cacert.gigi.output.Outputable; import org.cacert.gigi.output.template.Template; import org.cacert.gigi.pages.Page; -import org.cacert.gigi.ping.SSLPinger; -import org.cacert.gigi.util.RandomToken; public class DomainAddForm extends Form { @@ -26,15 +20,12 @@ public class DomainAddForm extends Form { private User target; - private String tokenName = RandomToken.generateToken(8); + PingconfigForm pcf; - private String tokenValue = RandomToken.generateToken(16); - - private static final int MAX_SSL_TESTS = 4; - - public DomainAddForm(HttpServletRequest hsr, User target) { + public DomainAddForm(HttpServletRequest hsr, User target) throws GigiApiException { super(hsr); this.target = target; + pcf = new PingconfigForm(hsr, null); } @Override @@ -46,35 +37,8 @@ public class DomainAddForm extends Form { } Domain d = new Domain(target, parameter); d.insert(); - if (req.getParameter("emailType") != null) { - String mail = AUTHORATIVE_EMAILS[Integer.parseInt(req.getParameter("email"))]; - d.addPing("email", mail); - } - if (req.getParameter("DNSType") != null) { - d.addPing("dns", tokenName + ":" + tokenValue); - } - if (req.getParameter("HTTPType") != null) { - d.addPing("http", tokenName + ":" + tokenValue); - } - if (req.getParameter("SSLType") != null) { - List types = Arrays.asList(SSLPinger.TYPES); - for (int i = 0; i < MAX_SSL_TESTS; i++) { - String type = req.getParameter("ssl-type-" + i); - String port = req.getParameter("ssl-port-" + i); - if (type == null || port == null || port.equals("")) { - continue; - } - int portInt = Integer.parseInt(port); - if ("direct".equals(type)) { - d.addPing("ssl", port); - } else if (types.contains(type)) { - d.addPing("ssl", portInt + ":" + type); - } - - } - } - Gigi.notifyPinger(); - + pcf.setTarget(d); + pcf.submit(out, req); return true; } catch (NumberFormatException e) { new GigiApiException("A number could not be parsed").format(out, Page.getLanguage(req)); @@ -85,27 +49,13 @@ public class DomainAddForm extends Form { } } - public static final String[] AUTHORATIVE_EMAILS = new String[] { - "root", "hostmaster", "postmaster", "admin", "webmaster" - }; - @Override protected void outputContent(PrintWriter out, Language l, Map vars) { - vars.put("tokenName", tokenName); - vars.put("tokenValue", tokenValue); - vars.put("authEmails", new OutputableArrayIterable(AUTHORATIVE_EMAILS, "email")); - vars.put("ssl-services", new IterableDataset() { - - int counter = 0; + vars.put("pingconfig", new Outputable() { @Override - public boolean next(Language l, Map vars) { - if (counter >= MAX_SSL_TESTS) { - return false; - } - vars.put("i", counter); - counter++; - return true; + public void output(PrintWriter out, Language l, Map vars) { + pcf.outputEmbeddableContent(out, l, vars); } }); t.output(out, l, vars); diff --git a/src/org/cacert/gigi/pages/account/DomainAddForm.templ b/src/org/cacert/gigi/pages/account/DomainAddForm.templ index c6040547..9c6de6b5 100644 --- a/src/org/cacert/gigi/pages/account/DomainAddForm.templ +++ b/src/org/cacert/gigi/pages/account/DomainAddForm.templ @@ -9,71 +9,7 @@ ( example.org) - - - - - - - - - - Select the destination mail address:
- - -
- - - - - - - - - - - - Please insert the following DNS TXT entry into the Zone-file of your domain:
-
-        ._cacert._auth IN TXT 
-        
- - - - - - - - - - -
http://example.org/cacert-.txt

-
- - - - - - - - - - - : - - - - -
- Port:
- - - + diff --git a/src/org/cacert/gigi/pages/account/DomainDetails.templ b/src/org/cacert/gigi/pages/account/DomainDetails.templ index 650f87ad..a0784185 100644 --- a/src/org/cacert/gigi/pages/account/DomainDetails.templ +++ b/src/org/cacert/gigi/pages/account/DomainDetails.templ @@ -3,13 +3,17 @@ - + + + - \ No newline at end of file + +
+ \ No newline at end of file diff --git a/src/org/cacert/gigi/pages/account/DomainOverview.java b/src/org/cacert/gigi/pages/account/DomainOverview.java index 82151771..4a216634 100644 --- a/src/org/cacert/gigi/pages/account/DomainOverview.java +++ b/src/org/cacert/gigi/pages/account/DomainOverview.java @@ -9,6 +9,8 @@ import javax.servlet.http.HttpServletResponse; import org.cacert.gigi.GigiApiException; import org.cacert.gigi.dbObjects.Domain; +import org.cacert.gigi.dbObjects.Domain.DomainPingExecution; +import org.cacert.gigi.dbObjects.DomainPingConfiguration; import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.localisation.Language; import org.cacert.gigi.output.Form; @@ -39,9 +41,10 @@ public class DomainOverview extends Page { return; } try { - final String[][] pings = d.getPings(); + final DomainPingExecution[] pings = d.getPings(); HashMap vars = new HashMap<>(); vars.put("domainname", d.getSuffix()); + vars.put("pingconfig", new PingconfigForm(req, d)); vars.put("pings", new IterableDataset() { int counter = 0; @@ -51,15 +54,19 @@ public class DomainOverview extends Page { if (counter >= pings.length) { return false; } - vars.put("state", pings[counter][0]); - vars.put("type", pings[counter][1]); - vars.put("config", pings[counter][2]); - String ping3 = pings[counter][3]; + vars.put("state", pings[counter].getState()); + vars.put("type", pings[counter].getType()); + vars.put("config", pings[counter].getInfo()); + String ping3 = pings[counter].getResult(); if (ping3 == null) { vars.put("result", ""); } else { vars.put("result", ping3); } + DomainPingConfiguration dpc = pings[counter].getConfig(); + if (dpc != null) { + vars.put("configId", Integer.toString(dpc.getId())); + } counter++; return true; } @@ -71,13 +78,17 @@ public class DomainOverview extends Page { } } - DomainManagementForm domMan = new DomainManagementForm(req, u); - DomainAddForm domAdd = new DomainAddForm(req, u); - HashMap vars = new HashMap<>(); - vars.put("doms", u.getDomains()); - vars.put("domainman", domMan); - vars.put("domainadd", domAdd); - getDefaultTemplate().output(resp.getWriter(), getLanguage(req), vars); + try { + DomainManagementForm domMan = new DomainManagementForm(req, u); + DomainAddForm domAdd = new DomainAddForm(req, u); + HashMap vars = new HashMap<>(); + vars.put("doms", u.getDomains()); + vars.put("domainman", domMan); + vars.put("domainadd", domAdd); + getDefaultTemplate().output(resp.getWriter(), getLanguage(req), vars); + } catch (GigiApiException e) { + e.format(resp.getWriter(), getLanguage(req)); + } } @Override diff --git a/src/org/cacert/gigi/pages/account/PingconfigForm.java b/src/org/cacert/gigi/pages/account/PingconfigForm.java new file mode 100644 index 00000000..51523cbb --- /dev/null +++ b/src/org/cacert/gigi/pages/account/PingconfigForm.java @@ -0,0 +1,214 @@ +package org.cacert.gigi.pages.account; + +import java.io.PrintWriter; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; + +import org.cacert.gigi.Gigi; +import org.cacert.gigi.GigiApiException; +import org.cacert.gigi.dbObjects.Domain; +import org.cacert.gigi.dbObjects.DomainPingConfiguration; +import org.cacert.gigi.dbObjects.DomainPingConfiguration.PingType; +import org.cacert.gigi.localisation.Language; +import org.cacert.gigi.output.Form; +import org.cacert.gigi.output.template.IterableDataset; +import org.cacert.gigi.output.template.Template; +import org.cacert.gigi.ping.SSLPinger; +import org.cacert.gigi.util.RandomToken; + +public class PingconfigForm extends Form { + + public enum SSLType { + DIRECT, XMPP, XMPP_SERVER, SMTP, IMAP; + + @Override + public String toString() { + return super.toString().toLowerCase(); + } + } + + private Domain target; + + private String tokenName = RandomToken.generateToken(8); + + private String tokenValue = RandomToken.generateToken(16); + + private static final int MAX_SSL_TESTS = 4; + + public static final String[] AUTHORATIVE_EMAILS = new String[] { + "root", "hostmaster", "postmaster", "admin", "webmaster" + }; + + private int selectedMail = -1; + + private boolean doMail, doDNS, doHTTP, doSSL; + + private int[] ports = new int[MAX_SSL_TESTS]; + + private SSLType[] sslTypes = new SSLType[MAX_SSL_TESTS]; + + private final Template t = new Template(PingconfigForm.class.getResource("PingconfigForm.templ")); + + public PingconfigForm(HttpServletRequest hsr, Domain target) throws GigiApiException { + super(hsr); + this.target = target; + if (target == null) { + return; + } + List configs = target.getConfiguredPings(); + int portpos = 0; + for (DomainPingConfiguration dpc : configs) { + switch (dpc.getType()) { + case EMAIL: + doMail = true; + for (int i = 0; i < AUTHORATIVE_EMAILS.length; i++) { + if (AUTHORATIVE_EMAILS[i].equals(dpc.getInfo())) { + selectedMail = i; + } + } + break; + case DNS: { + doDNS = true; + String[] parts = dpc.getInfo().split(":"); + tokenName = parts[0]; + tokenValue = parts[1]; + break; + } + case HTTP: { + doHTTP = true; + String[] parts = dpc.getInfo().split(":"); + tokenName = parts[0]; + tokenValue = parts[1]; + break; + } + case SSL: { + doSSL = true; + String[] parts = dpc.getInfo().split(":"); + ports[portpos] = Integer.parseInt(parts[0]); + if (parts.length == 2) { + sslTypes[portpos] = SSLType.valueOf(parts[1].toUpperCase()); + } else { + sslTypes[portpos] = SSLType.DIRECT; + } + portpos++; + break; + } + } + } + } + + public void setTarget(Domain target) { + this.target = target; + } + + @Override + public boolean submit(PrintWriter out, HttpServletRequest req) throws GigiApiException { + if (req.getParameter("emailType") != null) { + String mail = AUTHORATIVE_EMAILS[Integer.parseInt(req.getParameter("email"))]; + target.addPing(PingType.EMAIL, mail); + } + if (req.getParameter("DNSType") != null) { + target.addPing(PingType.DNS, tokenName + ":" + tokenValue); + } + if (req.getParameter("HTTPType") != null) { + target.addPing(PingType.HTTP, tokenName + ":" + tokenValue); + } + if (req.getParameter("SSLType") != null) { + List types = Arrays.asList(SSLPinger.TYPES); + for (int i = 0; i < MAX_SSL_TESTS; i++) { + String type = req.getParameter("ssl-type-" + i); + String port = req.getParameter("ssl-port-" + i); + if (type == null || port == null || port.equals("")) { + continue; + } + int portInt = Integer.parseInt(port); + if ("direct".equals(type)) { + target.addPing(PingType.SSL, port); + } else if (types.contains(type)) { + target.addPing(PingType.SSL, portInt + ":" + type); + } + + } + } + Gigi.notifyPinger(); + return false; + } + + @Override + protected void outputContent(PrintWriter out, Language l, Map vars) { + out.print(""); + outputEmbeddableContent(out, l, vars); + out.print("
"); + } + + protected void outputEmbeddableContent(PrintWriter out, Language l, Map vars) { + vars.put("tokenName", tokenName); + vars.put("tokenValue", tokenValue); + vars.put("authEmails", new IterableDataset() { + + int i = 0; + + @Override + public boolean next(Language l, Map vars) { + if (i >= AUTHORATIVE_EMAILS.length) { + return false; + } + vars.put("i", i); + vars.put("email", AUTHORATIVE_EMAILS[i]); + if (i == selectedMail) { + vars.put("checked", " checked=\"checked\""); + } else { + vars.put("checked", ""); + } + + i++; + return true; + } + }); + vars.put("mail", doMail ? " checked=\"checked\"" : ""); + vars.put("dns", doDNS ? " checked=\"checked\"" : ""); + vars.put("http", doHTTP ? " checked=\"checked\"" : ""); + vars.put("ssl", doSSL ? " checked=\"checked\"" : ""); + vars.put("ssl-services", new IterableDataset() { + + int counter = 0; + + @Override + public boolean next(Language l, Map vars) { + if (counter >= MAX_SSL_TESTS) { + return false; + } + vars.put("i", counter); + vars.put("port", ports[counter] == 0 ? "" : Integer.toString(ports[counter])); + final SSLType selectedType = sslTypes[counter]; + vars.put("ssl-types", new IterableDataset() { + + int i = 0; + + SSLType[] type = SSLType.values(); + + @Override + public boolean next(Language l, Map vars) { + if (i >= type.length) { + return false; + } + vars.put("name", type[i].toString()); + if (selectedType == type[i]) { + vars.put("selected", " selected=\"selected\""); + } else { + vars.put("selected", ""); + } + i++; + return true; + } + }); + counter++; + return true; + } + }); + t.output(out, l, vars); + } +} diff --git a/src/org/cacert/gigi/pages/account/PingconfigForm.templ b/src/org/cacert/gigi/pages/account/PingconfigForm.templ new file mode 100644 index 00000000..6a3bb060 --- /dev/null +++ b/src/org/cacert/gigi/pages/account/PingconfigForm.templ @@ -0,0 +1,62 @@ + + + + > + + + + + + Select the destination mail address:
+ + /> +
+ + + + + + > + + + + + + Please insert the following DNS TXT entry into the Zone-file of your domain:
+
+        ._cacert._auth IN TXT 
+        
+ + + + + > + + + + + +
http://example.org/cacert-.txt

+
+ + + + + > + + + + + + : + + + + +
+ Port:
+ + + \ No newline at end of file diff --git a/src/org/cacert/gigi/ping/PingerDaemon.java b/src/org/cacert/gigi/ping/PingerDaemon.java index 4ed4eb4b..806f7c76 100644 --- a/src/org/cacert/gigi/ping/PingerDaemon.java +++ b/src/org/cacert/gigi/ping/PingerDaemon.java @@ -5,9 +5,9 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashMap; - import org.cacert.gigi.database.DatabaseConnection; import org.cacert.gigi.dbObjects.Domain; +import org.cacert.gigi.dbObjects.DomainPingConfiguration; import org.cacert.gigi.dbObjects.User; import org.cacert.gigi.util.RandomToken; @@ -28,7 +28,7 @@ public class PingerDaemon extends Thread { @Override public void run() { try { - searchNeededPings = DatabaseConnection.getInstance().prepare("SELECT pingconfig.*, domains.domain, domains.memid FROM pingconfig LEFT JOIN domainPinglog ON domainPinglog.configId=pingconfig.id INNER JOIN domains ON domains.id=pingconfig.domainid WHERE domainPinglog.configId IS NULL "); + searchNeededPings = DatabaseConnection.getInstance().prepare("SELECT pingconfig.*, domains.domain, domains.memid FROM pingconfig LEFT JOIN domainPinglog ON domainPinglog.configId=pingconfig.id INNER JOIN domains ON domains.id=pingconfig.domainid WHERE domainPinglog.configId IS NULL AND domains.deleted IS NULL "); enterPingResult = DatabaseConnection.getInstance().prepare("INSERT INTO domainPinglog SET configId=?, state=?, result=?, challenge=?"); pingers.put("email", new EmailPinger()); pingers.put("ssl", new SSLPinger(truststore)); @@ -72,4 +72,6 @@ public class PingerDaemon extends Thread { } } } + + public void requestReping(DomainPingConfiguration dpc) {} }