Skip to content

Commit

Permalink
Adjust long polling failure handling (#119)
Browse files Browse the repository at this point in the history
Match A-Trust exception handling for long polling; wait 10 seconds then
retry.
This should hopefully ensure that any errors they mask, we also mask...

cf. #117
  • Loading branch information
iaik-jheher committed Apr 2, 2024
1 parent 00a38d3 commit ff09e04
Showing 1 changed file with 39 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.hc.core5.http.ProtocolException;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.message.BasicNameValuePair;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
Expand Down Expand Up @@ -235,6 +236,7 @@ public String handleSLRequest(PdfAs4SLRequest slRequest) throws SignatureExcepti
return post;
}

@Slf4j
private static class LongPollThread extends Thread implements AutoCloseable {

private final CloseableHttpClient httpClient = HttpClientUtils.builderWithSettings().build();
Expand All @@ -245,50 +247,69 @@ private static class LongPollThread extends Thread implements AutoCloseable {
@Override
public void run() {
long timeout = System.nanoTime() + (300l * 1000l * 1000l * 1000l); /* a-trust timeout is 5 minutes */
log.debug("longPollThread hello");
while (!done) {
log.debug("LongPollThread Making request to {}...", request.getRequestUri());
try (final CloseableHttpResponse response = httpClient.execute(request)) {
JSONObject jsonResponse = new JSONObject(EntityUtils.toString(response.getEntity()));
if (jsonResponse.getBoolean("Fin"))
signal.run();
else if (jsonResponse.getBoolean("Wait"))
{
log.debug("longPollThread continue...");
continue;
String jsonResponseStr = EntityUtils.toString(response.getEntity());
JSONObject jsonResponse = null;
try {
jsonResponse = new JSONObject(jsonResponseStr);
log.debug("Got long poll response:\n{}", jsonResponse.toString(2));
} catch (JSONException e) {
log.warn("Failed to parse long poll response:\n\"{}\"", jsonResponseStr);
throw e;
}
else if (jsonResponse.getBoolean("Error"))
signal.run(); /* will trigger reload and find error; this is the same thing a-trust does */
else {
if (jsonResponse.getBoolean("Fin")) {
signalProbablyDone();
} else if (jsonResponse.getBoolean("Wait")) {
continue;
} else if (jsonResponse.getBoolean("Error")) {
signalProbablyDone(); /* will trigger reload and find error; this is the same thing a-trust does */
} else {
log.warn("Unknown long poll response:\n{}", jsonResponse.toString(2));
break;
}
} catch (NoHttpResponseException e) {
if (timeout <= System.nanoTime())
signal.run(); /* reload to find the timeout error */
if (timeout <= System.nanoTime()) {
log.debug("LongPollThread no response, expecting A-Trust timeout, triggering reload...");
signalProbablyDone(); /* reload main page to find the timeout error */
}
continue; /* httpclient timeout */
} catch (IOException | ParseException | IllegalStateException e) {
} catch (Exception e) {
if (done) break;
log.warn("QR code long polling exception", e);
/* sleep so we don't hammer a-trust too hard in case this goes wrong */
try { Thread.sleep(5000); } catch (InterruptedException e2) {}

/* A-Trust does excepting handling this way, so we copy it (they might mask errors, so we should too...) */
try { Thread.sleep(10000); } catch (InterruptedException e2) {}
signalProbablyDone();
}
}
log.debug("longPollThread goodbye");
log.debug("LongPollThread goodbye");
}

private void signalProbablyDone() {
this.signal.run();
/* so we don't send a second request that immediately gets aborted */
try { Thread.sleep(500); } catch (InterruptedException e2) {}
}

public LongPollThread(URI uri, Runnable signal) {
log.debug("LongPollThread setup for '{}'", uri);
this.request = new HttpGet(uri);
this.signal = signal;
}

@Override
public void close() {
done = true;

if (this.request != null)
this.request.abort();

if (this.isAlive())
if (this.isAlive()) {
this.interrupt();
try { this.join(1000); } catch (InterruptedException e) {}
}

if (this.httpClient != null)
try { this.httpClient.close(); } catch (IOException e) { log.warn("Auto-close of long-poll HTTP client threw exception", e); }
Expand Down

0 comments on commit ff09e04

Please sign in to comment.