introduce extra RTP state to handle going from sending proceed to receiving retract

This commit is contained in:
Daniel Gultsch 2020-05-09 21:35:21 +02:00
parent 9b8b4f1791
commit 2c5bed61a1
5 changed files with 29 additions and 9 deletions

View file

@ -843,7 +843,7 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
if (serverMsgId == null) {
serverMsgId = extractStanzaId(account, packet);
}
mXmppConnectionService.getJingleConnectionManager().deliverMessage(account, packet.getTo(), packet.getFrom(), child, serverMsgId, timestamp);
mXmppConnectionService.getJingleConnectionManager().deliverMessage(account, packet.getTo(), packet.getFrom(), child, remoteMsgId, serverMsgId, timestamp);
} else if (query.isCatchup()) {
final String sessionId = child.getAttribute("id");
if (sessionId == null) {

View file

@ -74,7 +74,8 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
private static final List<RtpEndUserState> END_CARD = Arrays.asList(
RtpEndUserState.APPLICATION_ERROR,
RtpEndUserState.DECLINED_OR_BUSY,
RtpEndUserState.CONNECTIVITY_ERROR
RtpEndUserState.CONNECTIVITY_ERROR,
RtpEndUserState.RETRACTED
);
private static final String PROXIMITY_WAKE_LOCK_TAG = "conversations:in-rtp-session";
private static final int REQUEST_ACCEPT_CALL = 0x1111;

View file

@ -113,6 +113,7 @@ public abstract class AbstractJingleConnection {
PROCEED,
REJECTED,
RETRACTED,
RETRACTED_RACED, //used when receiving a retract after we already asked to proceed
SESSION_INITIALIZED, //equal to 'PENDING'
SESSION_INITIALIZED_PRE_APPROVED,
SESSION_ACCEPTED, //equal to 'ACTIVE'

View file

@ -154,7 +154,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
account.getXmppConnection().sendIqPacket(response, null);
}
public void deliverMessage(final Account account, final Jid to, final Jid from, final Element message, String serverMsgId, long timestamp) {
public void deliverMessage(final Account account, final Jid to, final Jid from, final Element message, String remoteMsgId, String serverMsgId, long timestamp) {
Preconditions.checkArgument(Namespace.JINGLE_MESSAGE.equals(message.getNamespace()));
final String sessionId = message.getAttribute("id");
if (sessionId == null) {
@ -174,6 +174,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
return;
}
final boolean fromSelf = from.asBareJid().equals(account.getJid().asBareJid());
final boolean addressedDirectly = to != null && to.equals(account.getJid());
final AbstractJingleConnection.Id id;
if (fromSelf) {
if (to != null && to.isFullJid()) {
@ -250,7 +251,7 @@ public class JingleConnectionManager extends AbstractConnectionManager {
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": unable to react to proposed session with " + rtpDescriptions.size() + " rtp descriptions of " + descriptions.size() + " total descriptions");
}
} else if ("proceed".equals(message.getName())) {
} else if (addressedDirectly && "proceed".equals(message.getName())) {
synchronized (rtpSessionProposals) {
final RtpSessionProposal proposal = getRtpSessionProposal(account, from.asBareJid(), sessionId);
if (proposal != null) {
@ -262,10 +263,21 @@ public class JingleConnectionManager extends AbstractConnectionManager {
rtpConnection.deliveryMessage(from, message, serverMsgId, timestamp);
} else {
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": no rtp session proposal found for " + from + " to deliver proceed");
//TODO return error message "item-not-found"
if (remoteMsgId == null) {
return;
}
final MessagePacket errorMessage = new MessagePacket();
errorMessage.setTo(from);
errorMessage.setId(remoteMsgId);
errorMessage.setType(MessagePacket.TYPE_ERROR);
final Element error = errorMessage.addChild("error");
error.setAttribute("code", "404");
error.setAttribute("type", "cancel");
error.addChild("item-not-found", "urn:ietf:params:xml:ns:xmpp-stanzas");
mXmppConnectionService.sendMessagePacket(account, errorMessage);
}
}
} else if ("reject".equals(message.getName())) {
} else if (addressedDirectly && "reject".equals(message.getName())) {
final RtpSessionProposal proposal = new RtpSessionProposal(account, from.asBareJid(), sessionId);
synchronized (rtpSessionProposals) {
if (rtpSessionProposals.remove(proposal) != null) {

View file

@ -61,6 +61,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
State.ACCEPTED,
State.REJECTED,
State.RETRACTED,
State.RETRACTED_RACED,
State.TERMINATED_SUCCESS,
State.TERMINATED_DECLINED_OR_BUSY,
State.TERMINATED_CONNECTIVITY_ERROR,
@ -86,6 +87,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
State.TERMINATED_CONNECTIVITY_ERROR //only used when the xmpp connection rebinds
));
transitionBuilder.put(State.PROCEED, ImmutableList.of(
State.RETRACTED_RACED,
State.SESSION_INITIALIZED_PRE_APPROVED,
State.TERMINATED_SUCCESS,
State.TERMINATED_APPLICATION_FAILURE,
@ -486,7 +488,6 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
}
void deliverFailedProceed() {
//TODO do we want a special State.ITEM_NOT_FOUND to track retracted calls during network outages
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": receive message error for proceed message");
if (transition(State.TERMINATED_CONNECTIVITY_ERROR)) {
webRTCWrapper.close();
@ -617,14 +618,17 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
private void receiveRetract(final Jid from, final String serverMsgId, final long timestamp) {
if (from.equals(id.with)) {
if (transition(State.RETRACTED)) {
final State target = this.state == State.PROCEED ? State.RETRACTED_RACED : State.RETRACTED;
if (transition(target)) {
xmppConnectionService.getNotificationService().cancelIncomingCallNotification();
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": session with " + id.with + " has been retracted (serverMsgId=" + serverMsgId + ")");
if (serverMsgId != null) {
this.message.setServerMsgId(serverMsgId);
}
this.message.setTime(timestamp);
this.message.markUnread();
if (target == State.RETRACTED) {
this.message.markUnread();
}
writeLogMessageMissed();
finish();
} else {
@ -811,6 +815,8 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
case RETRACTED:
case TERMINATED_CANCEL_OR_TIMEOUT:
return RtpEndUserState.ENDED;
case RETRACTED_RACED:
return RtpEndUserState.RETRACTED;
case TERMINATED_CONNECTIVITY_ERROR:
return RtpEndUserState.CONNECTIVITY_ERROR;
case TERMINATED_APPLICATION_FAILURE: