require dtls and ensure procceds get tracked
This commit is contained in:
parent
0661c1bd37
commit
6884e427ef
|
@ -238,7 +238,7 @@ public class MessageGenerator extends AbstractGenerator {
|
||||||
final MessagePacket packet = new MessagePacket();
|
final MessagePacket packet = new MessagePacket();
|
||||||
packet.setType(MessagePacket.TYPE_CHAT); //we want to carbon copy those
|
packet.setType(MessagePacket.TYPE_CHAT); //we want to carbon copy those
|
||||||
packet.setTo(proposal.with);
|
packet.setTo(proposal.with);
|
||||||
packet.setId(JingleRtpConnection.JINGLE_MESSAGE_ID_PREFIX+proposal.sessionId);
|
packet.setId(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX +proposal.sessionId);
|
||||||
final Element propose = packet.addChild("propose", Namespace.JINGLE_MESSAGE);
|
final Element propose = packet.addChild("propose", Namespace.JINGLE_MESSAGE);
|
||||||
propose.setAttribute("id", proposal.sessionId);
|
propose.setAttribute("id", proposal.sessionId);
|
||||||
propose.addChild("description", Namespace.JINGLE_APPS_RTP);
|
propose.addChild("description", Namespace.JINGLE_APPS_RTP);
|
||||||
|
|
|
@ -306,12 +306,17 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
final Jid from = packet.getFrom();
|
final Jid from = packet.getFrom();
|
||||||
final String id = packet.getId();
|
final String id = packet.getId();
|
||||||
if (from != null && id != null) {
|
if (from != null && id != null) {
|
||||||
if (id.startsWith(JingleRtpConnection.JINGLE_MESSAGE_ID_PREFIX)) {
|
if (id.startsWith(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX)) {
|
||||||
final String sessionId = id.substring(JingleRtpConnection.JINGLE_MESSAGE_ID_PREFIX.length());
|
final String sessionId = id.substring(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX.length());
|
||||||
mXmppConnectionService.getJingleConnectionManager()
|
mXmppConnectionService.getJingleConnectionManager()
|
||||||
.updateProposedSessionDiscovered(account, from, sessionId, JingleConnectionManager.DeviceDiscoveryState.FAILED);
|
.updateProposedSessionDiscovered(account, from, sessionId, JingleConnectionManager.DeviceDiscoveryState.FAILED);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (id.startsWith(JingleRtpConnection.JINGLE_MESSAGE_PROCEED_ID_PREFIX)) {
|
||||||
|
final String sessionId = id.substring(JingleRtpConnection.JINGLE_MESSAGE_PROCEED_ID_PREFIX.length());
|
||||||
|
mXmppConnectionService.getJingleConnectionManager().failProceed(account, from, sessionId);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
mXmppConnectionService.markMessage(account,
|
mXmppConnectionService.markMessage(account,
|
||||||
from.asBareJid(),
|
from.asBareJid(),
|
||||||
id,
|
id,
|
||||||
|
@ -845,8 +850,8 @@ public class MessageParser extends AbstractParser implements OnMessagePacketRece
|
||||||
query.removePendingReceiptRequest(new ReceiptRequest(packet.getTo(), id));
|
query.removePendingReceiptRequest(new ReceiptRequest(packet.getTo(), id));
|
||||||
}
|
}
|
||||||
} else if (id != null) {
|
} else if (id != null) {
|
||||||
if (id.startsWith(JingleRtpConnection.JINGLE_MESSAGE_ID_PREFIX)) {
|
if (id.startsWith(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX)) {
|
||||||
final String sessionId = id.substring(JingleRtpConnection.JINGLE_MESSAGE_ID_PREFIX.length());
|
final String sessionId = id.substring(JingleRtpConnection.JINGLE_MESSAGE_PROPOSE_ID_PREFIX.length());
|
||||||
mXmppConnectionService.getJingleConnectionManager()
|
mXmppConnectionService.getJingleConnectionManager()
|
||||||
.updateProposedSessionDiscovered(account, from, sessionId, JingleConnectionManager.DeviceDiscoveryState.DISCOVERED);
|
.updateProposedSessionDiscovered(account, from, sessionId, JingleConnectionManager.DeviceDiscoveryState.DISCOVERED);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -11,7 +11,8 @@ import rocks.xmpp.addr.Jid;
|
||||||
|
|
||||||
public abstract class AbstractJingleConnection {
|
public abstract class AbstractJingleConnection {
|
||||||
|
|
||||||
public static final String JINGLE_MESSAGE_ID_PREFIX = "jm-propose-";
|
public static final String JINGLE_MESSAGE_PROPOSE_ID_PREFIX = "jm-propose-";
|
||||||
|
public static final String JINGLE_MESSAGE_PROCEED_ID_PREFIX = "jm-proceed-";
|
||||||
|
|
||||||
protected final JingleConnectionManager jingleConnectionManager;
|
protected final JingleConnectionManager jingleConnectionManager;
|
||||||
protected final XmppConnectionService xmppConnectionService;
|
protected final XmppConnectionService xmppConnectionService;
|
||||||
|
|
|
@ -354,6 +354,14 @@ public class JingleConnectionManager extends AbstractConnectionManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void failProceed(Account account, final Jid with, String sessionId) {
|
||||||
|
final AbstractJingleConnection.Id id = AbstractJingleConnection.Id.of(account, with, sessionId);
|
||||||
|
final AbstractJingleConnection existingJingleConnection = connections.get(id);
|
||||||
|
if (existingJingleConnection instanceof JingleRtpConnection) {
|
||||||
|
((JingleRtpConnection) existingJingleConnection).deliverFailedProceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class RtpSessionProposal {
|
public static class RtpSessionProposal {
|
||||||
private final Account account;
|
private final Account account;
|
||||||
public final Jid with;
|
public final Jid with;
|
||||||
|
|
|
@ -81,7 +81,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
private RtpContentMap responderRtpContentMap;
|
private RtpContentMap responderRtpContentMap;
|
||||||
|
|
||||||
|
|
||||||
public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
||||||
super(jingleConnectionManager, id, initiator);
|
super(jingleConnectionManager, id, initiator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,8 +186,8 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
try {
|
try {
|
||||||
contentMap = RtpContentMap.of(jinglePacket);
|
contentMap = RtpContentMap.of(jinglePacket);
|
||||||
contentMap.requireContentDescriptions();
|
contentMap.requireContentDescriptions();
|
||||||
//TODO requireTransportWithDtls();
|
contentMap.requireDTLSFingerprint();
|
||||||
} catch (IllegalArgumentException | IllegalStateException | NullPointerException e) {
|
} catch (final IllegalArgumentException | IllegalStateException | NullPointerException e) {
|
||||||
respondOk(jinglePacket);
|
respondOk(jinglePacket);
|
||||||
sendSessionTerminate(Reason.FAILED_APPLICATION);
|
sendSessionTerminate(Reason.FAILED_APPLICATION);
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents", e);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents", e);
|
||||||
|
@ -226,7 +226,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
try {
|
try {
|
||||||
contentMap = RtpContentMap.of(jinglePacket);
|
contentMap = RtpContentMap.of(jinglePacket);
|
||||||
contentMap.requireContentDescriptions();
|
contentMap.requireContentDescriptions();
|
||||||
//TODO requireTransportWithDtls();
|
contentMap.requireDTLSFingerprint();
|
||||||
} catch (IllegalArgumentException | IllegalStateException | NullPointerException e) {
|
} catch (IllegalArgumentException | IllegalStateException | NullPointerException e) {
|
||||||
respondOk(jinglePacket);
|
respondOk(jinglePacket);
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents in session-accept", e);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents in session-accept", e);
|
||||||
|
@ -351,6 +351,15 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void deliverFailedProceed() {
|
||||||
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": receive message error for proceed message");
|
||||||
|
if (transition(State.TERMINATED_CONNECTIVITY_ERROR)) {
|
||||||
|
webRTCWrapper.close();
|
||||||
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": transitioned into connectivity error");
|
||||||
|
this.jingleConnectionManager.finishConnection(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void receiveAccept(Jid from, Element message) {
|
private void receiveAccept(Jid from, Element message) {
|
||||||
final boolean originatedFromMyself = from.asBareJid().equals(id.account.getJid().asBareJid());
|
final boolean originatedFromMyself = from.asBareJid().equals(id.account.getJid().asBareJid());
|
||||||
if (originatedFromMyself) {
|
if (originatedFromMyself) {
|
||||||
|
@ -533,7 +542,7 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
}
|
}
|
||||||
|
|
||||||
private void terminateWithOutOfOrder(final JinglePacket jinglePacket) {
|
private void terminateWithOutOfOrder(final JinglePacket jinglePacket) {
|
||||||
Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": terminating session with out-of-order");
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": terminating session with out-of-order");
|
||||||
webRTCWrapper.close();
|
webRTCWrapper.close();
|
||||||
transitionOrThrow(State.TERMINATED_APPLICATION_FAILURE);
|
transitionOrThrow(State.TERMINATED_APPLICATION_FAILURE);
|
||||||
respondWithOutOfOrder(jinglePacket);
|
respondWithOutOfOrder(jinglePacket);
|
||||||
|
@ -681,6 +690,9 @@ public class JingleRtpConnection extends AbstractJingleConnection implements Web
|
||||||
|
|
||||||
private void sendJingleMessage(final String action, final Jid to) {
|
private void sendJingleMessage(final String action, final Jid to) {
|
||||||
final MessagePacket messagePacket = new MessagePacket();
|
final MessagePacket messagePacket = new MessagePacket();
|
||||||
|
if ("proceed".equals(action)) {
|
||||||
|
messagePacket.setId(JINGLE_MESSAGE_PROCEED_ID_PREFIX + id.sessionId);
|
||||||
|
}
|
||||||
messagePacket.setType(MessagePacket.TYPE_CHAT); //we want to carbon copy those
|
messagePacket.setType(MessagePacket.TYPE_CHAT); //we want to carbon copy those
|
||||||
messagePacket.setTo(to);
|
messagePacket.setTo(to);
|
||||||
messagePacket.addChild(action, Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId);
|
messagePacket.addChild(action, Namespace.JINGLE_MESSAGE).setAttribute("id", id.sessionId);
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
@ -51,13 +52,26 @@ public class RtpContentMap {
|
||||||
if (this.contents.size() == 0) {
|
if (this.contents.size() == 0) {
|
||||||
throw new IllegalStateException("No contents available");
|
throw new IllegalStateException("No contents available");
|
||||||
}
|
}
|
||||||
for(Map.Entry<String,DescriptionTransport> entry : this.contents.entrySet()) {
|
for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
|
||||||
if (entry.getValue().description == null) {
|
if (entry.getValue().description == null) {
|
||||||
throw new IllegalStateException(String.format("%s is lacking content description", entry.getKey()));
|
throw new IllegalStateException(String.format("%s is lacking content description", entry.getKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void requireDTLSFingerprint() {
|
||||||
|
if (this.contents.size() == 0) {
|
||||||
|
throw new IllegalStateException("No contents available");
|
||||||
|
}
|
||||||
|
for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
|
||||||
|
final IceUdpTransportInfo transport = entry.getValue().transport;
|
||||||
|
final IceUdpTransportInfo.Fingerprint fingerprint = transport.getFingerprint();
|
||||||
|
if (fingerprint == null || Strings.isNullOrEmpty(fingerprint.getContent()) || Strings.isNullOrEmpty(fingerprint.getHash())) {
|
||||||
|
throw new SecurityException(String.format("Use of DTLS-SRTP (XEP-0320) is required for content %s", entry.getKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public JinglePacket toJinglePacket(final JinglePacket.Action action, final String sessionId) {
|
public JinglePacket toJinglePacket(final JinglePacket.Action action, final String sessionId) {
|
||||||
final JinglePacket jinglePacket = new JinglePacket(action, sessionId);
|
final JinglePacket jinglePacket = new JinglePacket(action, sessionId);
|
||||||
if (this.group != null) {
|
if (this.group != null) {
|
||||||
|
@ -78,11 +92,11 @@ public class RtpContentMap {
|
||||||
final RtpContentMap.DescriptionTransport descriptionTransport = contents.get(contentName);
|
final RtpContentMap.DescriptionTransport descriptionTransport = contents.get(contentName);
|
||||||
final IceUdpTransportInfo transportInfo = descriptionTransport == null ? null : descriptionTransport.transport;
|
final IceUdpTransportInfo transportInfo = descriptionTransport == null ? null : descriptionTransport.transport;
|
||||||
if (transportInfo == null) {
|
if (transportInfo == null) {
|
||||||
throw new IllegalArgumentException("Unable to find transport info for content name "+contentName);
|
throw new IllegalArgumentException("Unable to find transport info for content name " + contentName);
|
||||||
}
|
}
|
||||||
final IceUdpTransportInfo newTransportInfo = transportInfo.cloneWrapper();
|
final IceUdpTransportInfo newTransportInfo = transportInfo.cloneWrapper();
|
||||||
newTransportInfo.addChild(candidate);
|
newTransportInfo.addChild(candidate);
|
||||||
return new RtpContentMap(null, ImmutableMap.of(contentName, new DescriptionTransport(null,newTransportInfo)));
|
return new RtpContentMap(null, ImmutableMap.of(contentName, new DescriptionTransport(null, newTransportInfo)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue