Closed brianjmurrell closed 5 years ago
network_unreachable is a intern setting used to prevent unwanted network operation that will fail. For example, when in doze mode, you can receive a push but you won't have network to make a REGISTER.
But how can _networkunreachable actually be true when a push was just received, on the network?
network operation that will fail
What is determining that a network operation will fail and how can it be determining that when clearly the network is working. A push was received on it.
How is linphone-android even usable if this state can exist?
There are two things on Android : the network of the device and the network an application has access to. Your device can be connected to internet and receive push notifications (firebase is part of Android so it benefits from features other applications can't have access to), but at the same time an app process can be restricted for network operations (in doze mode for example).
So this seems to make linphone unusable, or at least unreliable at best on Android. Am I interpreting you correctly?
So how do the many other applications that reliably get push notifications and content deal with this problem? Are other SIP clients such as Bria and Zoiper subject to the same unreliability? What makes linphone different if not?
Does any of this help? Or is what it's saying obsolete now?
I do have priority
set to high
in my push requests:
++ curl -s -X POST --header 'Authorization: Key=[redacted]' --Header 'Content-Type: application/json' -d '{
"to":"[redacted]",
"priority":"high",
"uuid":"<urn:uuid:f518cf03-dce8-4002-870e-8b948e08de61>",
"send-time":"2019-10-04 12:32:45"
}' https://fcm.googleapis.com/fcm/send
{"multicast_id":[redacted],"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:[redacted]%[redacted]"}]}
I'm asking the above as a legitimate question because all of this seems to put the utility of linphone-android in serious question.
But I do also wonder if and why this is only a problem for linphone-android.
Since the version you used we have made improvements to our network manager.
Is that in the app or the sdk?
Sdk
So I want 4.2-182-g1eb2091 instead of the 4.2-143-gfa00b73 that I had?
No actually there was no change in that part of code since the 4.2-143. What commit of the app are you on ?
d753ca23
Then I'm surprised. The logs you attached in the first comment of this ticket doesn't match the version you said you are using.
Ahhh. You are reminding me that I did update the app's master commit yesterday before I built with the new SDK.
I'm pretty sure it was 053ada28 that I was on before updating yesterday.
Anyway now that you are up-to-date it should not happen anymore.
Great
Still seems to be happening:
2019-10-11 07:56:05:206 [linphone-android] MESSAGE [Push Notification] Notifying Core
2019-10-11 07:56:05:206 [liblinphone] WARNING Refresh register operation not available (network unreachable)
Can you confirm you are using linphone-android with the background mode enabled ? I may have found a bug in the library that can happen in the Core still exists.
But anyway why in your log file doesn't appear the following log that is outputed at the very start of the native method we call when we receive a push notification: "Push notification received" ?
No, I am not using Background mode. I don't want it to stay awake in the background. I want it to be killable and then wake up when it receives a push notification. AFAIU background mode applications are frowned upon by Android and various phone makers with their aggressive battery savings techniques.
But anyway why in your log file doesn't appear the following log that is outputed at the very start of the native method we call when we receive a push notification: "Push notification received" ?
I don't know.
What method is called in the FirebaseMessaging class of your Android app when a push is received ?
Which Android app are you meaning? The only part of my solution that is Android is linphone.
The push message is being sent by my PBX to https://fcm.googleapis.com/fcm/send with:
Authorization: Key=[redacted]
Content-Type: application/json
{
"to":"[redacted]",
"priority":"high",
"uuid":"<urn:uuid:15e94074-4ff1-4898-a3b0-53371de4c354>",
"send-time":"2019-10-11 09:33:53"
}'
And I get a result that looks like:
{
"multicast_id":8168460656905932761,"success":1,"failure":0,"canonical_ids":0,"results": [{"message_id":"0:1570800833693584%fafd82ecf9fd7ecd"}]
}
In the android project, in java/org/linphone/firebase/FirebaseMessaging.java
Ahhh. Sorry, I understand what you mean now:
@@ -43,7 +43,7 @@ public class FirebaseMessaging extends FirebaseMessagingService {
if (LinphoneManager.getInstance() != null) {
Core core = LinphoneManager.getCore();
if (core != null) {
- core.ensureRegistered();
+ core.refreshRegisters();
}
}
}
Got another one of these:
2019-10-16 16:49:11:330 [linphone-android] MESSAGE [Push Notification] Notifying Core
2019-10-16 16:49:11:330 [liblinphone] WARNING Refresh register operation not available (network unreachable)
2019-10-16 16:49:11:417 [liblinphone] MESSAGE Destroying op [0x7bd2784c80] of type [SalOpUnknown]
2019-10-16 16:49:11:417 [belle-sip] MESSAGE Transaction [0x7bc32f8940] deleted
2019-10-16 16:49:11:418 [liblinphone] MESSAGE Destroying op [0x7bd2785680] of type [SalOpUnknown]
2019-10-16 16:49:11:418 [belle-sip] MESSAGE Transaction [0x7bc4418600] deleted
2019-10-16 16:49:11:419 [liblinphone] MESSAGE Destroying op [0x7bd2784f00] of type [SalOpUnknown]
2019-10-16 16:49:11:420 [belle-sip] MESSAGE Transaction [0x7bc05e4400] deleted
2019-10-16 16:49:11:420 [liblinphone] MESSAGE Destroying op [0x7bd2785e00] of type [SalOpUnknown]
2019-10-16 16:49:11:420 [belle-sip] MESSAGE Transaction [0x7bc05e5120] deleted
So seems it's not really fixed yet. I'm using version:
User-Agent: LinphoneAndroid/4.1-144-g60964c40 (FRD-L04) LinphoneSDK/4.2-182-g1eb2091 (master)
Can we please reopen this issue until it is resolved?
Did you revert your changes ? Because from the logs it looks like not. Anyway I recommend you to update the SDK to version 4.3.0-alpha-7-g64c3d80 or newer, I've changed a little thing in the network manager that could improve your situation.
Revert which changes? I don't see any comment about reverting changes.
update the SDK to version 4.3.0-alpha-7-g64c3d80 or newer
Is that simply a matter of clearing the gradle cache or is there a smaller hammer than clearing the entire gradle cache?
Revert which changes? I don't see any comment about reverting changes.
You have made changes to your FirebaseMessagingService implementation. This is your choice but then don't complain it doesn't work then.
Is that simply a matter of clearing the gradle cache or is there a smaller hammer than clearing the entire gradle cache?
You don't need to clear it, just building the app again in Android Studio should be enough once you changed the version in implementation "org.linphone:linphone-sdk-android:4.2+" to 4.3+.
You have made changes to your FirebaseMessagingService implementation. This is your choice but then don't complain it doesn't work then.
Do you honestly think that change is at the root of this issue though?
Besides, without this change, as I have asked before and not gotten a reasonable answer, how does the SIP proxy know linphone is ready to receive the INVITE without linphone telling it in some way, like sending a REGISTER?
Simply sending the push and waiting some arbitrary amount of time is completely unsuitable due to the variability in how long it takes linphone to (possibly have to) wake up and be ready. As a software developer, surely you can agree that a sleep here is never going to be exactly right. It's either going to be too long and callers give up waiting for the phone to be answered or it's too short and linphone isn't ready when the INVITE is sent and the call is missed.
If you have a better solution to the above problem than using a REGISTER to notify the SIP proxy that linphone is ready, I am completely open to suggestions.
changed the version in implementation "org.linphone:linphone-sdk-android:4.2+" to 4.3+.
Do you honestly think that change is at the root of this issue though?
Yes, as the work we do in ensureRegistered is specifically designed for this scenario and won't abort because the network reachability of the Core is set to false, at the contrary of refreshRegisters().
Simply sending the push and waiting some arbitrary amount of time
That's not what we do...
So does ensureRegistered()
somehow give linphone access to the network stack that refreshRegisters()
doesn't? So calling refreshRegisters()
after ensureRegistered()
should give it access to the network stack, yes?
That's not what we do...
Can you please describe what you do?
Building latest master with implementation "org.linphone:linphone-sdk-android:4.3+"
produces this crash:
10-17 10:01:18.909 9340 9340 D AndroidRuntime: Shutting down VM
10-17 10:01:18.911 9340 9340 E AndroidRuntime: FATAL EXCEPTION: main
10-17 10:01:18.911 9340 9340 E AndroidRuntime: Process: org.linphone.debug, PID: 9340
10-17 10:01:18.911 9340 9340 E AndroidRuntime: java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/org.linphone.debug-IsP0Umw6TE5skiysKKPnrA==/base.apk"],nativeLibraryDirectories=[/data/app/org.linphone.debug-IsP0Umw6TE5skiysKKPnrA==/lib/arm64, /data/app/org.linphone.debug-IsP0Umw6TE5skiysKKPnrA==/base.apk!/lib/arm64-v8a, /system/lib64, /vendor/lib64, /product/lib64]]] couldn't find "libc++_shared.so"
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at java.lang.Runtime.loadLibrary0(Runtime.java:1011)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at java.lang.System.loadLibrary(System.java:1660)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at org.linphone.core.FactoryImpl.<clinit>(Factory.java:295)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at org.linphone.core.Factory.instance(Factory.java:44)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at org.linphone.LinphoneContext.<init>(LinphoneContext.java:95)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at org.linphone.LinphoneService.onCreate(LinphoneService.java:54)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.app.ActivityThread.handleCreateService(ActivityThread.java:3961)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.app.ActivityThread.-wrap5(Unknown Source:0)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2092)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:108)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.os.Looper.loop(Looper.java:166)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:7523)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
10-17 10:01:18.911 9340 9340 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
10-17 10:01:18.913 1109 1448 W ActivityManager: Force finishing activity org.linphone.debug/org.linphone.activities.LinphoneLauncherActivity
Reverting the implementation "org.linphone:linphone-sdk-android:4.3+"
and rebuilding/installing doesn't seem to fix the crash. :-(
That'll teach me to not keep previous copies of the .apk
s.
Just tried it, works like a charm. Clean your cache.
I can see that libc++_shared.so
is not being included in the .apk
. Let me try cleaning the cache...
Even after doing a rm -rf /home/brian/.gradle/caches/*
and running ./gradlew installDebug
the .apk
still only contains these libs:
15754304 00-00-1980 00:00 lib/arm64-v8a/liblinphone.so
4651048 00-00-1980 00:00 lib/arm64-v8a/libmediastreamer.so
43488 00-00-1980 00:00 lib/arm64-v8a/libmsaaudio.so
51456 00-00-1980 00:00 lib/arm64-v8a/libmsandroidcamera2.so
383080 00-00-1980 00:00 lib/arm64-v8a/libmswebrtc.so
12161424 00-00-1980 00:00 lib/armeabi-v7a/liblinphone.so
3631788 00-00-1980 00:00 lib/armeabi-v7a/libmediastreamer.so
26544 00-00-1980 00:00 lib/armeabi-v7a/libmsaaudio.so
34620 00-00-1980 00:00 lib/armeabi-v7a/libmsandroidcamera2.so
290524 00-00-1980 00:00 lib/armeabi-v7a/libmswebrtc.so
15098856 00-00-1980 00:00 lib/x86/liblinphone.so
4975300 00-00-1980 00:00 lib/x86/libmediastreamer.so
38784 00-00-1980 00:00 lib/x86/libmsaaudio.so
46856 00-00-1980 00:00 lib/x86/libmsandroidcamera2.so
372444 00-00-1980 00:00 lib/x86/libmswebrtc.so
15680952 00-00-1980 00:00 lib/x86_64/liblinphone.so
4967360 00-00-1980 00:00 lib/x86_64/libmediastreamer.so
43776 00-00-1980 00:00 lib/x86_64/libmsaaudio.so
51736 00-00-1980 00:00 lib/x86_64/libmsandroidcamera2.so
387496 00-00-1980 00:00 lib/x86_64/libmswebrtc.so
I even checked out linphone-android master and see the same thing.
Hrm. git clean -dfx
seems to have resolved it.
So back to the open questions in the thread:
That's not what we do...
Can you please describe what you do?
Can you please describe how a SIP proxy is to know that linphone is ready for an INVITE if you don't send it a signal, such as a REGISTER when it wake up?
Yeah, there is an issue with trying to go to the 4.3+ SDK without doing a git clean -dfx
before ./gradlew installDebug
that causes some libs to be missing from the .apk
,
Can you please describe how a SIP proxy is to know that linphone is ready for an INVITE if you don't send it a signal, such as a REGISTER when it wake up?
Take a look at the code in linphone project at the ensureRegistered method, it is quite well documented.
Ahhh. Let me see if I can guess at what is going on here...
linphone REGISTER
s to the SIP proxy on a TCP connection. The SIP proxy uses the state of that TCP connection to know if linphone is still alive or not because when the phone kills linphone, the TCP session will be torn down.
So as long as the TCP socket is still in the ESTABLISHED
state on the SIP proxy, the SIP proxy knows linphone is still alive and ready to receive an INVITE
-- it probably doesn't even need to send a push!. If the TCP session is torn down, then the SIP proxy knows linphone has been killed and has to send a push and wait for a REGISTER
before it can send an INVITE
.
Correspondingly, ensureRegistered()
is effectively implementing the above protocol. If the connection to the proxy is still in an ESTABLISHED
state, it does nothing because it knows the SIP server knows it's still alive. However if the TCP session is no longer ESTABLISHED
, for example, because linphone has been woken up (by way of a push) from being previously killed, it knows it has to REGISTER
again to let the SIP proxy know it's alive.
So this is basically just an optimization of the protocol I was using which was to always push and always REGISTER
after receiving a push.
There is problem with your protocol however. Some phones, mine included, will stop responding to TCP sessions when it goes into doze mode. The TCP session is not actually torn down, with a TCP RST
or anything like that, the phone just stops responding to keepalives. This can be seen in a packet trace as TCP packets being sent from the SIP proxy to the phone with no response from the phone at all.
It further can be seen on the SIP proxy when the Send-Q
is > 0:
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 2002 10.75.22.8:5060 10.75.22.32:58234 ESTABLISHED 28946/asterisk
Sending a push when in this state doesn't result in linphone REGISTER
ing, so it must still be alive on the phone and the TCP session ESTABLISHED
even though the packets from the SIP proxy are not being responded to.
Here's a log of that happening. A push was sent to linphone here:
2019-10-18 12:47:44:194 [linphone-android] MESSAGE [Push Notification] Notifying Core
2019-10-18 12:47:44:195 [liblinphone] MESSAGE Push notification received
2019-10-18 12:49:47:250 [linphone-android] MESSAGE [Contacts Manager] Content observer detected a changing in at least one contact
2019-10-18 12:49:47:251 [linphone-android] MESSAGE [Contacts Manager] Synchronization started
2019-10-18 12:49:47:254 [linphone-android] MESSAGE [Contacts Manager] Background synchronization started
2019-10-18 12:49:47:254 [linphone-android] MESSAGE [Contacts Manager] Only fetching contacts in default directory
2019-10-18 12:49:47:315 [linphone-android] MESSAGE [Contacts Manager] Found 1260 entries in cursor
but as you can see nothing was done by linphone after the push was received until a couple of minutes later.
Issue should be fixed in SDK 4.3.0-alpha.25+f810940
Actually not fixed. Linphone SDK: 4.3.3 Android 10 device
On register Push received, the refreshRegisters is called in a job scheduled via work manager with NetworkType.CONNECTED Constraints.
Job is started but even after it gives the same error as Refresh register operation not available (network unreachable)
The attached log will show that the internet is connected via wifi.
Without logs from the SDK I can't say what's happening. Also don't use any SDK method on a different thread than the main one!
I got a failure to receive an
INVITE
with only the following messages related to the call in the debug log:It's puzzling how the
network unreachable
state could be true when clearly linphone just received a push message over the network.