package com.zsoft.SignalA.Transport.Longpolling; import org.json.JSONObject; import android.os.Handler; import com.turbomanage.httpclient.AsyncCallback; import com.turbomanage.httpclient.HttpResponse; import com.zsoft.SignalA.ConnectionBase; import com.zsoft.SignalA.ConnectionState; import com.zsoft.SignalA.SignalAUtils; import com.zsoft.SignalA.SendCallback; import com.zsoft.SignalA.Transport.ProcessResult; import com.zsoft.SignalA.Transport.TransportHelper; import com.zsoft.parallelhttpclient.ParallelHttpClient; public class ReconnectingState extends StopableStateWithCallback { public ReconnectingState(ConnectionBase connection) { super(connection); } @Override public ConnectionState getState() { return ConnectionState.Reconnecting; } @Override public void Start() { } @Override public void Send(CharSequence text, SendCallback callback) { callback.OnError(new Exception("Not connected")); } @Override protected void OnRun() { if(DoStop()) return; if (mConnection.getMessageId() == null) { // No message received yet....connect instead of reconnect mConnection.SetNewState(new ConnectingState(mConnection)); return; } String url = SignalAUtils.EnsureEndsWith(mConnection.getUrl(), "/"); url += "reconnect"; url += TransportHelper.GetReceiveQueryString(mConnection, null, TRANSPORT_NAME); AsyncCallback cb = new AsyncCallback() { @Override public void onComplete(HttpResponse httpResponse) { if(DoStop()) return; try { if(httpResponse.getStatus()==200) { JSONObject json = JSONHelper.ToJSONObject(httpResponse.getBodyAsString()); if (json!=null) { ProcessResult result = TransportHelper.ProcessResponse(mConnection, json); if(result.processingFailed) { mConnection.setError(new Exception("Error while proccessing response.")); } else if(result.disconnected) { mConnection.SetNewState(new DisconnectedState(mConnection)); return; } } else { mConnection.setError(new Exception("Error when parsing response to JSONObject.")); } } else { mConnection.setError(new Exception("Error when calling endpoint. Returncode: " + httpResponse.getStatus())); } } finally { if(mConnection.getCurrentState() == ReconnectingState.this) { // Delay before reconnecting Delay(2000, new DelayCallback() { @Override public void OnStopedBeforeElapsed() { mIsRunning.set(false); mConnection.SetNewState(new DisconnectedState(mConnection)); } @Override public void OnDelayElapsed() { mIsRunning.set(false); // Loop if we are still reconnecting Run(); } }); } } } @Override public void onError(Exception ex) { mConnection.setError(ex); } }; synchronized (mCallbackLock) { //mCurrentCallback = cb; } ParallelHttpClient httpClient = new ParallelHttpClient(); httpClient.setMaxRetries(1); httpClient.post(url, null, cb); } protected void Delay(final long milliSeconds, final DelayCallback cb) { final long startTime = System.currentTimeMillis(); final Handler handler = new Handler(); final Runnable runnable = new Runnable() { @Override public void run() { if(DoStop()) { cb.OnStopedBeforeElapsed(); } else { long difference = System.currentTimeMillis() - startTime; if(difference < milliSeconds) { handler.postDelayed(this, 500); } else { cb.OnDelayElapsed(); } } } }; handler.postDelayed(runnable, 500); } private abstract class DelayCallback { public abstract void OnDelayElapsed(); public abstract void OnStopedBeforeElapsed(); } }