sdp candidate to transport-info

This commit is contained in:
Daniel Gultsch 2020-04-05 13:58:05 +02:00
parent 4d70855b4c
commit 2591a96945
3 changed files with 112 additions and 6 deletions

View file

@ -42,6 +42,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
}
private State state = State.NULL;
private RtpContentMap initialRtpContentMap;
public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
@ -152,9 +153,32 @@ public class JingleRtpConnection extends AbstractJingleConnection {
}
private void sendSessionInitiate(RtpContentMap rtpContentMap) {
Log.d(Config.LOGTAG, rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId).toString());
this.initialRtpContentMap = rtpContentMap;
final JinglePacket sessionInitiate = rtpContentMap.toJinglePacket(JinglePacket.Action.SESSION_INITIATE, id.sessionId);
Log.d(Config.LOGTAG, sessionInitiate.toString());
send(sessionInitiate);
}
private void sendTransportInfo(final String contentName, IceUdpTransportInfo.Candidate candidate) {
final RtpContentMap transportInfo;
try {
transportInfo = this.initialRtpContentMap.transportInfo(contentName, candidate);
} catch (Exception e) {
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": unable to prepare transport-info from candidate for content=" + contentName);
return;
}
final JinglePacket jinglePacket = transportInfo.toJinglePacket(JinglePacket.Action.TRANSPORT_INFO, id.sessionId);
Log.d(Config.LOGTAG, jinglePacket.toString());
send(jinglePacket);
}
private void send(final JinglePacket jinglePacket) {
jinglePacket.setTo(id.with);
//TODO track errors
xmppConnectionService.sendIqPacket(id.account, jinglePacket, null);
}
private void sendSessionAccept() {
Log.d(Config.LOGTAG, "sending session-accept");
}
@ -186,7 +210,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
stream.addTrack(audioTrack);
PeerConnection peer = peerConnectionFactory.createPeerConnection(Collections.emptyList(), new PeerConnection.Observer() {
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(Collections.emptyList(), new PeerConnection.Observer() {
@Override
public void onSignalingChange(PeerConnection.SignalingState signalingState) {
@ -204,11 +228,16 @@ public class JingleRtpConnection extends AbstractJingleConnection {
@Override
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
Log.d(Config.LOGTAG, "onIceGatheringChange() " + iceGatheringState);
}
@Override
public void onIceCandidate(IceCandidate iceCandidate) {
IceUdpTransportInfo.Candidate candidate = IceUdpTransportInfo.Candidate.fromSdpAttribute(iceCandidate.sdp);
Log.d(Config.LOGTAG, "onIceCandidate: " + iceCandidate.sdp);
Log.d(Config.LOGTAG, "xml: " + candidate.toString());
Log.d(Config.LOGTAG, "mid: " + iceCandidate.sdpMid);
sendTransportInfo(iceCandidate.sdpMid, candidate);
}
@ -243,9 +272,9 @@ public class JingleRtpConnection extends AbstractJingleConnection {
}
});
peer.addStream(stream);
peerConnection.addStream(stream);
peer.createOffer(new SdpObserver() {
peerConnection.createOffer(new SdpObserver() {
@Override
public void onCreateSuccess(org.webrtc.SessionDescription description) {
@ -253,6 +282,27 @@ public class JingleRtpConnection extends AbstractJingleConnection {
Log.d(Config.LOGTAG, "description: " + description.description);
final RtpContentMap rtpContentMap = RtpContentMap.of(sessionDescription);
sendSessionInitiate(rtpContentMap);
peerConnection.setLocalDescription(new SdpObserver() {
@Override
public void onCreateSuccess(org.webrtc.SessionDescription sessionDescription) {
}
@Override
public void onSetSuccess() {
Log.d(Config.LOGTAG, "onSetSuccess()");
}
@Override
public void onCreateFailure(String s) {
}
@Override
public void onSetFailure(String s) {
}
}, description);
}
@Override

View file

@ -54,13 +54,27 @@ public class RtpContentMap {
}
for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
final Content content = new Content(Content.Creator.INITIATOR, entry.getKey());
content.addChild(entry.getValue().description);
if (entry.getValue().description != null) {
content.addChild(entry.getValue().description);
}
content.addChild(entry.getValue().transport);
jinglePacket.addJingleContent(content);
}
return jinglePacket;
}
public RtpContentMap transportInfo(final String contentName, final IceUdpTransportInfo.Candidate candidate) {
final RtpContentMap.DescriptionTransport descriptionTransport = contents.get(contentName);
final IceUdpTransportInfo transportInfo = descriptionTransport == null ? null : descriptionTransport.transport;
if (transportInfo == null) {
throw new IllegalArgumentException("Unable to find transport info for content name "+contentName);
}
final IceUdpTransportInfo newTransportInfo = transportInfo.cloneWrapper();
newTransportInfo.addChild(candidate);
return new RtpContentMap(null, ImmutableMap.of(contentName, new DescriptionTransport(null,newTransportInfo)));
}
public static class DescriptionTransport {
public final RtpDescription description;
public final IceUdpTransportInfo transport;

View file

@ -1,12 +1,17 @@
package eu.siacs.conversations.xmpp.jingle.stanzas;
import android.util.Log;
import com.google.common.base.Preconditions;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xml.Namespace;
import eu.siacs.conversations.xmpp.jingle.SessionDescription;
@ -41,6 +46,12 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
return transportInfo;
}
public IceUdpTransportInfo cloneWrapper() {
final IceUdpTransportInfo transportInfo = new IceUdpTransportInfo();
transportInfo.setAttributes(new Hashtable<>(getAttributes()));
return transportInfo;
}
public static IceUdpTransportInfo of(SessionDescription sessionDescription, SessionDescription.Media media) {
final String ufrag = Iterables.getFirst(media.attributes.get("ice-ufrag"), null);
final String pwd = Iterables.getFirst(media.attributes.get("ice-pwd"), null);
@ -132,6 +143,37 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
candidate.setChildren(element.getChildren());
return candidate;
}
// https://tools.ietf.org/html/draft-ietf-mmusic-ice-sip-sdp-39#section-5.1
public static Candidate fromSdpAttribute(final String attribute) {
final String[] pair = attribute.split(":", 2);
if (pair.length == 2 && "candidate".equals(pair[0])) {
final String[] segments = pair[1].split(" ");
if (segments.length >= 6) {
final String foundation = segments[0];
final String component = segments[1];
final String transport = segments[2];
final String priority = segments[3];
final String connectionAddress = segments[4];
final String port = segments[5];
final HashMap<String, String> additional = new HashMap<>();
for (int i = 6; i < segments.length - 1; i = i + 2) {
additional.put(segments[i], segments[i + 1]);
}
final Candidate candidate = new Candidate();
candidate.setAttribute("component", component);
candidate.setAttribute("foundation", foundation);
candidate.setAttribute("generation", additional.get("generation"));
candidate.setAttribute("ip", connectionAddress);
candidate.setAttribute("port", port);
candidate.setAttribute("priority", priority);
candidate.setAttribute("protocol", transport);
candidate.setAttribute("type", additional.get("typ"));
return candidate;
}
}
return null;
}
}