sdp candidate to transport-info
This commit is contained in:
parent
4d70855b4c
commit
2591a96945
|
@ -42,6 +42,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
private State state = State.NULL;
|
private State state = State.NULL;
|
||||||
|
private RtpContentMap initialRtpContentMap;
|
||||||
|
|
||||||
|
|
||||||
public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
public JingleRtpConnection(JingleConnectionManager jingleConnectionManager, Id id, Jid initiator) {
|
||||||
|
@ -152,9 +153,32 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendSessionInitiate(RtpContentMap rtpContentMap) {
|
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() {
|
private void sendSessionAccept() {
|
||||||
Log.d(Config.LOGTAG, "sending session-accept");
|
Log.d(Config.LOGTAG, "sending session-accept");
|
||||||
}
|
}
|
||||||
|
@ -186,7 +210,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
stream.addTrack(audioTrack);
|
stream.addTrack(audioTrack);
|
||||||
|
|
||||||
|
|
||||||
PeerConnection peer = peerConnectionFactory.createPeerConnection(Collections.emptyList(), new PeerConnection.Observer() {
|
PeerConnection peerConnection = peerConnectionFactory.createPeerConnection(Collections.emptyList(), new PeerConnection.Observer() {
|
||||||
@Override
|
@Override
|
||||||
public void onSignalingChange(PeerConnection.SignalingState signalingState) {
|
public void onSignalingChange(PeerConnection.SignalingState signalingState) {
|
||||||
|
|
||||||
|
@ -204,11 +228,16 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
|
public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) {
|
||||||
|
Log.d(Config.LOGTAG, "onIceGatheringChange() " + iceGatheringState);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onIceCandidate(IceCandidate iceCandidate) {
|
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
|
@Override
|
||||||
public void onCreateSuccess(org.webrtc.SessionDescription description) {
|
public void onCreateSuccess(org.webrtc.SessionDescription description) {
|
||||||
|
@ -253,6 +282,27 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
Log.d(Config.LOGTAG, "description: " + description.description);
|
Log.d(Config.LOGTAG, "description: " + description.description);
|
||||||
final RtpContentMap rtpContentMap = RtpContentMap.of(sessionDescription);
|
final RtpContentMap rtpContentMap = RtpContentMap.of(sessionDescription);
|
||||||
sendSessionInitiate(rtpContentMap);
|
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
|
@Override
|
||||||
|
|
|
@ -54,13 +54,27 @@ public class RtpContentMap {
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
|
for (Map.Entry<String, DescriptionTransport> entry : this.contents.entrySet()) {
|
||||||
final Content content = new Content(Content.Creator.INITIATOR, entry.getKey());
|
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);
|
content.addChild(entry.getValue().transport);
|
||||||
jinglePacket.addJingleContent(content);
|
jinglePacket.addJingleContent(content);
|
||||||
}
|
}
|
||||||
return jinglePacket;
|
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 static class DescriptionTransport {
|
||||||
public final RtpDescription description;
|
public final RtpDescription description;
|
||||||
public final IceUdpTransportInfo transport;
|
public final IceUdpTransportInfo transport;
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
import com.google.common.collect.ArrayListMultimap;
|
import com.google.common.collect.ArrayListMultimap;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import eu.siacs.conversations.Config;
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
import eu.siacs.conversations.xmpp.jingle.SessionDescription;
|
import eu.siacs.conversations.xmpp.jingle.SessionDescription;
|
||||||
|
@ -41,6 +46,12 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
|
||||||
return transportInfo;
|
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) {
|
public static IceUdpTransportInfo of(SessionDescription sessionDescription, SessionDescription.Media media) {
|
||||||
final String ufrag = Iterables.getFirst(media.attributes.get("ice-ufrag"), null);
|
final String ufrag = Iterables.getFirst(media.attributes.get("ice-ufrag"), null);
|
||||||
final String pwd = Iterables.getFirst(media.attributes.get("ice-pwd"), 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());
|
candidate.setChildren(element.getChildren());
|
||||||
return candidate;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue