Commit 1ad711c6 authored by Matthew Finkel's avatar Matthew Finkel
Browse files

fixup! Bug 40028: Implement Tor Service controller

Define enum class for tor's status and define current state using
the enums.
parent 0585f943
Loading
Loading
Loading
Loading
+65 −11
Original line number Diff line number Diff line
@@ -30,6 +30,31 @@ interface TorEvents {
    fun onTorStopped()
}

private enum class TorStatus {
    OFF,
    STARTING,
    ON,
    STOPPING,
    UNKNOWN;

    fun getStateFromString(status: String) : TorStatus{
        return when (status) {
            TorServiceConstants.STATUS_ON -> ON
            TorServiceConstants.STATUS_STARTING -> STARTING
            TorServiceConstants.STATUS_STOPPING -> STOPPING
            TorServiceConstants.STATUS_OFF -> OFF
            else -> UNKNOWN
        }
    }

    fun isOff() = this == OFF
    fun isOn() = this == ON
    fun isStarting() = this == STARTING
    fun isStarted() = ((this == TorStatus.STARTING) || (this == TorStatus.ON))
    fun isStopping() = this == STOPPING
    fun isUnknown() = this == UNKNOWN
}

class TorController(
    private val context: Context
) : TorEvents {
@@ -43,15 +68,23 @@ class TorController(
    private var pendingRegisterChangeList = mutableListOf<Pair<TorEvents, Boolean>>()
    private var lockTorListenersMutation = false

    private var isTorStarted = false
    private var lastKnownStatus = TorStatus.OFF
    private var wasTorBootstrapped = false
    private var isTorRestarting = false

    // This may be a lie
    private var isTorBootstrapped = false
        get() = ((lastKnownStatus == TorStatus.ON) && wasTorBootstrapped)

    val isDebugLoggingEnabled get() =
        context.
        getSharedPreferences("org.torproject.android_preferences", Context.MODE_PRIVATE).
        getBoolean("pref_enable_logging", false)

    val isStarting get() = lastKnownStatus.isStarting()
    val isRestarting get() = isTorRestarting
    val isBootstrapped get() = isTorBootstrapped
    val isConnected get() = (lastKnownStatus.isStarted() && !isTorRestarting)

    fun start() {
        // Register receiver
@@ -93,22 +126,41 @@ class TorController(
                return
            }

            entries.add(Pair(logentry, status))

            onTorStatusUpdate(logentry, status)
            if (status != null && status.startsWith("ON")) {
                isTorStarted = true

            if (status == null) {
                return
            }

            val newStatus = lastKnownStatus.getStateFromString(status)

            if (newStatus.isUnknown()) {
                if (wasTorBootstrapped) {
                    stopTor()
                }
            }

            entries.add(Pair(logentry, status))

            if (logentry != null && logentry.contains(TorServiceConstants.TOR_CONTROL_PORT_MSG_BOOTSTRAP_DONE)) {
                isTorBootstrapped = true
                wasTorBootstrapped = true
                onTorConnected()
            }

            if (isTorStarted && status != null && status.startsWith("OFF")) {
                setTorStopped()
            if (lastKnownStatus.isStopping() && newStatus.isOff()) {
                if (isTorRestarting) {
                    initiateTorBootstrap()
                } else {
                    onTorStopped()
                }
            }

            if (lastKnownStatus.isOff() && newStatus.isStarting()) {
                isTorRestarting = false
            }

            lastKnownStatus = newStatus
        }
    }

    override fun onTorConnecting() {
@@ -251,8 +303,7 @@ class TorController(
    }

    fun setTorStopped() {
        isTorStarted = false
        isTorBootstrapped = false
        lastKnownStatus = TorStatus.OFF
        onTorStopped()
    }

@@ -265,12 +316,15 @@ class TorController(
            return
        }

        isTorRestarting = true
        if (!lastKnownStatus.isStarted() && wasTorBootstrapped) {
            // If we aren't started, but we were previously bootstrapped,
            // then we handle a "restart" request as a "start" restart
            initiateTorBootstrap()
        } else {
            // |isTorRestarting| tracks the state of restart. When we receive an |OFF| state
            // from TorService in persistentBroadcastReceiver::onReceive we restart the Tor
            // service.
            isTorRestarting = true
            stopTor()
        }
    }