package freenet.client.connection; import com.google.gwt.http.client.Request; import com.google.gwt.http.client.RequestCallback; import com.google.gwt.http.client.Response; import com.google.gwt.user.client.Timer; import freenet.client.FreenetJs; import freenet.client.UpdaterConstants; import freenet.client.tools.FreenetRequest; import freenet.client.tools.QueryParameter; import freenet.client.update.IUpdateManager; /** This ConnectionManager manages a long polling connection, that keeps a connection open at all times */ public class LongPollingConnectionManager implements IConnectionManager { /** The UpdateManager that gets notified when data is received */ private IUpdateManager updateManager; /** The number of failed requests after the last successful one */ private int numOfFailedRequests = 0; /** The last sent request */ private Request sentRequest = null; /** Is running? */ private boolean running = false; public LongPollingConnectionManager(IUpdateManager updateManager) { this.updateManager = updateManager; } @Override public void closeConnection() { running = false; if (sentRequest != null && sentRequest.isPending()) { // If there is a connection open, then closes it sentRequest.cancel(); } } @Override public void openConnection() { if (updateManager == null) { throw new RuntimeException("You must set the UpdateManager before opening the connection!"); } running = true; sendRequest(); } /** Schedules the next request. It waits more and more as more requests fails, but will try forever. */ private void scheduleNextRequest() { new Timer() { @Override public void run() { // When run, send a request sendRequest(); } }.schedule(Math.max(Math.min((int) Math.pow(2, (numOfFailedRequests++)), 10000),50));// Waits more if requests failing, but a max at 10sec FreenetJs.log("Next request scheduled"); } /** Sends a request */ private void sendRequest() { // Only send if running if (running == true) { sentRequest = FreenetRequest.sendRequest(UpdaterConstants.notificationPath, new QueryParameter("requestId", FreenetJs.requestId), new RequestCallback() { @Override public void onResponseReceived(Request request, Response response) { FreenetJs.log("AJAX response:success:" + (response.getText().startsWith(UpdaterConstants.SUCCESS) ? "true" : "false")); if (response.getText().startsWith(UpdaterConstants.SUCCESS)) { // If success, then notify the UpdateManager numOfFailedRequests = 0; updateManager.updated(response.getText().substring("SUCCESS:".length())); } if (response.getText().startsWith(UpdaterConstants.FAILURE)) { // If failure, then there are no pushed elements on the page, so the stopping is expected FreenetJs.isPushingCancelledExpected = true; FreenetJs.stop(); } // Schedules the next request scheduleNextRequest(); } @Override public void onError(Request request, Throwable exception) { // If errorous, then try again FreenetJs.log("AJAX response:ERROR"); scheduleNextRequest(); } }); } } }