AnchorFreePartner / hydrasdk-demo-android

Hydra VPN SDK demo app for Android
https://developer.anchorfree.com/
60 stars 31 forks source link

Multiple exceptions in production that we cannot reproduce and fix #123

Closed Nevaehy closed 3 years ago

Nevaehy commented 3 years ago

Hi. We released an application with hydrasdk and tracking a many sdk exceptions. Could you please guide me through them? What is it and how can I fix it?

image

timoshenkoav commented 3 years ago

Hi, Why do you track all of this as exceptions? 1 - wrong state to call start - you call start vpn when its not in IDLE state 2- can happen when user changes the network connection when vpn is on 3 - user cancelled the vpn permission dialog 4 - call stop vpn while start in process 5 - cannot do a backend call due to network problem 6 - trying to connect when user daily traffic exceed 7 - ? 8 - calling api methods when is not logged in 9 - failed to connect to openvpn server 10 - start vpn was called when stopping 11 - failed to connect to openvpn server

Nevaehy commented 3 years ago

Thank you. We are just tracking all negative scenarios and these scenarios have the above exceptions.

7 - what can it be? any guesses?

timoshenkoav commented 3 years ago

7 i can be a lot of cases. need the log

Nevaehy commented 3 years ago

I see. Unfortunately the log cannot be provided by the metrics we use.

Nevaehy commented 3 years ago

I found that all these exceptions are generated only in the released .apk from Google Play. Meanwhile the same release and debug .apk directly from Android Studio work great.

timoshenkoav commented 3 years ago

what do you mean? Traffic exceed exception can be easily reproduced on debug build as well - the same as "connection broken" and "permission cancelled"

Nevaehy commented 3 years ago

All these exceptions are from the very first launch.

Nevaehy commented 3 years ago

Also, are there other reasons for Connection Broken and Wrong State to Call Start exceptions? Because the percentage is huge, and I doubt that 25% changes network state upon VPN enabling, and the .start() is called only after checking the VPN current state:

        UnifiedSDK.getVpnState(object : Callback<VPNState> {
            override fun success(vpnState: VPNState) {
                when (vpnState) {
                    VPNState.CONNECTED -> disconnectFromVpn()
                    VPNState.IDLE -> checkConditionsAndConnect()
                    else -> view?.showError(UNKNOWN_ERROR)
                }
            }

            override fun failure(e: VpnException) {
                val error = if (e.message == null) "" else e.message!!
                view?.showError(UNKNOWN_ERROR)
            }
        })
timoshenkoav commented 3 years ago
  1. i dont know when you track this error
  2. try to reproduce it.
Nevaehy commented 3 years ago

All these errors in the released Google Play apk, when users try to connect to VPN (vpn.start() is called)

timoshenkoav commented 3 years ago

it cannot be tracked automatically - so i am asking the place where YOU track these errors

Nevaehy commented 3 years ago

I track it in override fun error()

private fun connectToVpn(isSubscribed: Boolean, country: String) {
        var currentCountry = country
        isLoggedIn(object : Callback<Boolean> {
            override fun success(aBoolean: Boolean) = if (aBoolean) {
                VPNUserFlow.logVPNLoginState(
                    view as? Activity,
                    true,
                    "",
                    true
                )
                if (currentCountry.isEmpty()) {
                    currentCountry = UnifiedSDK.COUNTRY_OPTIMAL
                    VPNSharedPrefsUtils(view as Activity).setCurrentCountry(currentCountry)
                }
                VPNSharedPrefsUtils(view as Activity).setPreviousCountry(currentCountry)

                if (VPNTimerService.unifiedSDK == null) {
                    view?.showError(UNKNOWN_ERROR)
                    VPNUserFlow.logConnectionAttempt(
                        view as? Activity,
                        false,
                        "UnifiedSDK is null"
                    )
                } else {
                    VPNUserFlow.logConnectionAttempt(
                        view as? Activity,
                        true,
                        ""
                    )
                    VPNTimerService.unifiedSDK!!.vpn.start(SessionConfig.Builder()
                        .withVirtualLocation(currentCountry)
                        .withReason(TrackingConstants.GprReasons.M_UI)
                        .withTransport(CaketubeTransport.TRANSPORT_ID_TCP)
                        .build(), object : CompletableCallback {

                        override fun complete() {
                            VPNUserFlow.logConnected(
                                view as? Activity,
                                isSubscribed,
                                country
                            )
                        }

                        override fun error(e: VpnException) {
                            view?.showError(CONNECT_ERROR)
                            VPNUserFlow.logConnectionError(
                                view as? Activity,
                                isSubscribed,
                                country,
                                e.toString()
                            )
                            Log.d("TESTT", if (e.message == null) "" else e.message!!)
                        }
                    })
                }
            } else {
                VPNUserFlow.logVPNLoginState(
                    view as? Activity,
                    true,
                    "",
                    false
                )
                loginToVpnAndConnect(isSubscribed, currentCountry)
            }

            override fun failure(p0: VpnException) {
                view?.showError(LOGGING_ERROR)
                val error = if (p0.message == null) "" else p0.message!!
                Log.d("TESTT", error)
                VPNUserFlow.logVPNLoginState(
                    view as? Activity,
                    false,
                    error,
                    false
                )
            }
        })
    }
timoshenkoav commented 3 years ago

Check your implementation for race conditions and leaks - you have a lot of wrong state. Btw 25% users does say anything about the count of success connections for this users. please share you project id - i can check our analytics for connection rate

timoshenkoav commented 3 years ago

sorry, i've mean app package name

Nevaehy commented 3 years ago

com.blazing.fast.vpn

timoshenkoav commented 3 years ago

due to our analytics most of your errors are "permission cancelled by user" The second is "connection broken" Btw, why do you use openvpn only? try to use hydra as primary transport - it should have better connection rate

Nevaehy commented 3 years ago

How to do that?

timoshenkoav commented 3 years ago

replace .withTransport(CaketubeTransport.TRANSPORT_ID_TCP) with .withTransport(HydraTransport.TRANSPORT_ID)

Nevaehy commented 3 years ago

and may I ask you to provide the percents from your analytics? How much for "permission cancelled by user" and "connection broken"?

timoshenkoav commented 3 years ago

permission cancel - 309 cancel start - 40 success - 343 traffic exceed - 23 network related - 19 connection broken - 662

The number is # of attempts. So switch to hydra to decrease "connection broken" %