Add functionality to send websocket keep-alives based on real time by dpapavas · Pull Request #53 · signalapp/libsignal-service-java

2 min read Original article ↗

I'm not sure if adding this as a reply to the relevant change request will hide it or not, so I'm posting it as a separate reply.

I added the timeout to the call to wait() in RealtimeSleepTimer, as requested, but I decided to add the requested while loop, meant to prevent premature keep-alives in the call to SleepTimer.sleep(), in the KeepAliveSender thread. As far as I can tell calls to Object.wait() and Thread.sleep() can be interrupted prematurely in exactly the same ways and putting the while loop inside RealtimeSleepTimer would cover only the non-GCM case. Since guarding against premature keep-alives is desirable, I suppose we should cover GCM-enabled devices as well.

I should note, that I'm not sure this is appropriate in any case though. As far as I can tell, calls to Object.wait() and Thread.sleep() can only be interrupted prematurely by interrupting the thread they've been called from. Since Signal's code doesn't interrupt its own threads, as far as I can tell, either the wait calls will never be interrupted prematurely, or if they are, the interrupt's source will be in 3rd party code and in that case, it's not at all clear, that the appropriate response would be to just keep on sleeping, at least not without investigating the specific reason for the interrupt first.

In any case, although the multiple ways to wake up (timeout and alarm) and the while loops complicate things a bit, keep-alives seem to be on time, whether the device is sleeping or not. One can calculate the times between keep-alives with the one-liner below, after the deivce has been sitting for some time:

adb logcat -d | grep "WebSocketConnection: Sending keep alive\.\.\." |
cut -d' ' -f2 | while IFS=. read t m; do l_1=$(date -d $t +"%s").$m &&
echo $l_1-$l_0 && l_0=$l_1; done | tail -n +1 | bc -l

In my case timing seems to be mostly exact, with some occasional delays of a second or two.

(PS: Let me know if you'd like me to squash the commit with the changes into the initial commit of the PR, to prevent unnecessary pollution of the commit history.)