From 1090b2edd33b969cdae715f56c71aeace635dbf4 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Thu, 18 Jan 2024 13:09:04 +0100 Subject: [PATCH] add optional strict offline checking for calls --- .../java/eu/siacs/conversations/Config.java | 2 ++ .../conversations/entities/Presences.java | 6 ++++ .../services/CallIntegration.java | 1 + .../CallIntegrationConnectionService.java | 28 ++++++++++----- .../conversations/ui/RtpSessionActivity.java | 5 ++- .../xmpp/jingle/RtpEndUserState.java | 35 ++++++++++--------- src/main/res/values/strings.xml | 1 + 7 files changed, 52 insertions(+), 26 deletions(-) diff --git a/src/main/java/eu/siacs/conversations/Config.java b/src/main/java/eu/siacs/conversations/Config.java index febe12b14..da3628b6f 100644 --- a/src/main/java/eu/siacs/conversations/Config.java +++ b/src/main/java/eu/siacs/conversations/Config.java @@ -121,6 +121,8 @@ public final class Config { false; // disables STUN/TURN and Proxy65 look up (useful to debug IBB fallback) public static final boolean USE_DIRECT_JINGLE_CANDIDATES = true; public static final boolean USE_JINGLE_MESSAGE_INIT = true; + + public static final boolean JINGLE_MESSAGE_INIT_STRICT_OFFLINE_CHECK = false; public static final boolean DISABLE_HTTP_UPLOAD = false; public static final boolean EXTENDED_SM_LOGGING = false; // log stanza counts public static final boolean BACKGROUND_STANZA_LOGGING = diff --git a/src/main/java/eu/siacs/conversations/entities/Presences.java b/src/main/java/eu/siacs/conversations/entities/Presences.java index 59480b0ce..d3bd706f8 100644 --- a/src/main/java/eu/siacs/conversations/entities/Presences.java +++ b/src/main/java/eu/siacs/conversations/entities/Presences.java @@ -83,6 +83,12 @@ public class Presences { } } + public boolean isEmpty() { + synchronized (this.presences) { + return this.presences.isEmpty(); + } + } + public String[] toResourceArray() { synchronized (this.presences) { final String[] presencesArray = new String[presences.size()]; diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegration.java b/src/main/java/eu/siacs/conversations/services/CallIntegration.java index 489d71256..f07ebe28d 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegration.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegration.java @@ -303,6 +303,7 @@ public class CallIntegration extends Connection { @Override public void onStateChanged(final int state) { Log.d(Config.LOGTAG, "onStateChanged(" + state + ")"); + // TODO devices before selfManaged() will likely have to play their own ringback sound if (state == STATE_ACTIVE) { playConnectedSound(); } else if (state == STATE_DISCONNECTED) { diff --git a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java index 99f565ff1..de39abb51 100644 --- a/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java +++ b/src/main/java/eu/siacs/conversations/services/CallIntegrationConnectionService.java @@ -97,15 +97,26 @@ public class CallIntegrationConnectionService extends ConnectionService { intent.putExtra(RtpSessionActivity.EXTRA_WITH, with.toEscapedString()); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); - final CallIntegration callIntegration; + final Connection callIntegration; if (with.isBareJid()) { - final var proposal = - service.getJingleConnectionManager() - .proposeJingleRtpSession(account, with, media); - - intent.putExtra( - RtpSessionActivity.EXTRA_LAST_REPORTED_STATE, - RtpEndUserState.FINDING_DEVICE.toString()); + final var contact = account.getRoster().getContact(with); + if (Config.JINGLE_MESSAGE_INIT_STRICT_OFFLINE_CHECK + && contact.getPresences().isEmpty()) { + intent.putExtra( + RtpSessionActivity.EXTRA_LAST_REPORTED_STATE, + RtpEndUserState.CONTACT_OFFLINE.toString()); + callIntegration = + Connection.createFailedConnection( + new DisconnectCause(DisconnectCause.ERROR, "contact is offline")); + } else { + final var proposal = + service.getJingleConnectionManager() + .proposeJingleRtpSession(account, with, media); + intent.putExtra( + RtpSessionActivity.EXTRA_LAST_REPORTED_STATE, + RtpEndUserState.FINDING_DEVICE.toString()); + callIntegration = proposal.getCallIntegration(); + } if (Media.audioOnly(media)) { intent.putExtra( RtpSessionActivity.EXTRA_LAST_ACTION, @@ -115,7 +126,6 @@ public class CallIntegrationConnectionService extends ConnectionService { RtpSessionActivity.EXTRA_LAST_ACTION, RtpSessionActivity.ACTION_MAKE_VIDEO_CALL); } - callIntegration = proposal.getCallIntegration(); } else { final JingleRtpConnection jingleRtpConnection = service.getJingleConnectionManager().initializeRtpSession(account, with, media); diff --git a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java index c40a49a72..ee0770023 100644 --- a/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/RtpSessionActivity.java @@ -95,6 +95,7 @@ public class RtpSessionActivity extends XmppActivity RtpEndUserState.APPLICATION_ERROR, RtpEndUserState.SECURITY_ERROR, RtpEndUserState.DECLINED_OR_BUSY, + RtpEndUserState.CONTACT_OFFLINE, RtpEndUserState.CONNECTIVITY_ERROR, RtpEndUserState.CONNECTIVITY_LOST_ERROR, RtpEndUserState.RETRACTED); @@ -881,6 +882,7 @@ public class RtpSessionActivity extends XmppActivity case FINDING_DEVICE -> setTitle(R.string.rtp_state_finding_device); case RINGING -> setTitle(R.string.rtp_state_ringing); case DECLINED_OR_BUSY -> setTitle(R.string.rtp_state_declined_or_busy); + case CONTACT_OFFLINE -> setTitle(R.string.rtp_state_contact_offline); case CONNECTIVITY_ERROR -> setTitle(R.string.rtp_state_connectivity_error); case CONNECTIVITY_LOST_ERROR -> setTitle(R.string.rtp_state_connectivity_lost_error); case RETRACTED -> setTitle(R.string.rtp_state_retracted); @@ -974,7 +976,8 @@ public class RtpSessionActivity extends XmppActivity this.binding.acceptCall.setOnClickListener((v -> acceptContentAdd(contentAddition))); this.binding.acceptCall.setImageResource(R.drawable.ic_baseline_check_24); this.binding.acceptCall.setVisibility(View.VISIBLE); - } else if (state == RtpEndUserState.DECLINED_OR_BUSY) { + } else if (asList(RtpEndUserState.DECLINED_OR_BUSY, RtpEndUserState.CONTACT_OFFLINE) + .contains(state)) { this.binding.rejectCall.setContentDescription(getString(R.string.exit)); this.binding.rejectCall.setOnClickListener(this::exit); this.binding.rejectCall.setImageResource(R.drawable.ic_clear_white_48dp); diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpEndUserState.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpEndUserState.java index 885820460..fff82031a 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpEndUserState.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/RtpEndUserState.java @@ -1,20 +1,23 @@ package eu.siacs.conversations.xmpp.jingle; public enum RtpEndUserState { - INCOMING_CALL, //received a 'propose' message - CONNECTING, //session-initiate or session-accepted but no webrtc peer connection yet - CONNECTED, //session-accepted and webrtc peer connection is connected - RECONNECTING, //session-accepted and webrtc peer connection was connected once but is currently disconnected or failed - INCOMING_CONTENT_ADD, //session-accepted with a pending, incoming content-add - FINDING_DEVICE, //'propose' has been sent out; no 184 ack yet - RINGING, //'propose' has been sent out and it has been 184 acked - ACCEPTING_CALL, //'proceed' message has been sent; but no session-initiate has been received - ENDING_CALL, //libwebrt says 'closed' but session-terminate has not gone through - ENDED, //close UI - DECLINED_OR_BUSY, //other party declined; no retry button - CONNECTIVITY_ERROR, //network error; retry button - CONNECTIVITY_LOST_ERROR, //network error but for call duration > 0 - RETRACTED, //user pressed home or power button during 'ringing' - shows retry button - APPLICATION_ERROR, //something rather bad happened; libwebrtc failed or we got in IQ-error - SECURITY_ERROR //problem with DTLS (missing) or verification + INCOMING_CALL, // received a 'propose' message + CONNECTING, // session-initiate or session-accepted but no webrtc peer connection yet + CONNECTED, // session-accepted and webrtc peer connection is connected + RECONNECTING, // session-accepted and webrtc peer connection was connected once but is currently + // disconnected or failed + INCOMING_CONTENT_ADD, // session-accepted with a pending, incoming content-add + FINDING_DEVICE, // 'propose' has been sent out; no 184 ack yet + RINGING, // 'propose' has been sent out and it has been 184 acked + ACCEPTING_CALL, // 'proceed' message has been sent; but no session-initiate has been received + ENDING_CALL, // libwebrt says 'closed' but session-terminate has not gone through + ENDED, // close UI + DECLINED_OR_BUSY, // other party declined; no retry button + CONTACT_OFFLINE, // when `JINGLE_MESSAGE_INIT_STRICT_OFFLINE_CHECK` is true this shows up when + // the contact is offline, generally similar to BUSY + CONNECTIVITY_ERROR, // network error; retry button + CONNECTIVITY_LOST_ERROR, // network error but for call duration > 0 + RETRACTED, // user pressed home or power button during 'ringing' - shows retry button + APPLICATION_ERROR, // something rather bad happened; libwebrtc failed or we got in IQ-error + SECURITY_ERROR // problem with DTLS (missing) or verification } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 996977eab..f47731d06 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -929,6 +929,7 @@ Discovering devices Ringing Busy + Contact is not available Could not connect call Connection lost Retracted call