From 5b1d86d67e65c6ed233055fcdfd5f354223d63f1 Mon Sep 17 00:00:00 2001 From: Daniel Gultsch Date: Sat, 4 Apr 2020 15:30:13 +0200 Subject: [PATCH] dummy code to get sdp out of (non-working) libwebrtc --- proguard-rules.pro | 1 + .../xmpp/jingle/JingleRtpConnection.java | 146 ++++++++++++++++-- .../xmpp/jingle/SessionDescription.java | 43 +++--- .../xmpp/jingle/stanzas/RtpDescription.java | 5 + 4 files changed, 159 insertions(+), 36 deletions(-) diff --git a/proguard-rules.pro b/proguard-rules.pro index 78cc2a0f9..d3ac8f30a 100644 --- a/proguard-rules.pro +++ b/proguard-rules.pro @@ -11,6 +11,7 @@ -keep class com.google.android.gms.** -keep class org.openintents.openpgp.* +-keep class org.webrtc.** { *; } -dontwarn org.bouncycastle.mail.** -dontwarn org.bouncycastle.x509.util.LDAPStoreHelper diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java index 399688266..3424b1ec7 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/JingleRtpConnection.java @@ -8,8 +8,19 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import org.checkerframework.checker.nullness.compatqual.NullableDecl; +import org.webrtc.AudioSource; +import org.webrtc.AudioTrack; +import org.webrtc.DataChannel; +import org.webrtc.IceCandidate; +import org.webrtc.MediaConstraints; +import org.webrtc.MediaStream; +import org.webrtc.PeerConnection; +import org.webrtc.PeerConnectionFactory; +import org.webrtc.RtpReceiver; +import org.webrtc.SdpObserver; import java.util.Collection; +import java.util.Collections; import java.util.Map; import eu.siacs.conversations.Config; @@ -66,10 +77,10 @@ public class JingleRtpConnection extends AbstractJingleConnection { try { contents = DescriptionTransport.of(jinglePacket.getJingleContents()); } catch (IllegalArgumentException | NullPointerException e) { - Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": improperly formatted contents",e); + Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": improperly formatted contents", e); return; } - Log.d(Config.LOGTAG,"processing session-init with "+contents.size()+" contents"); + Log.d(Config.LOGTAG, "processing session-init with " + contents.size() + " contents"); final State oldState = this.state; if (transition(State.SESSION_INITIALIZED)) { if (oldState == State.PROCEED) { @@ -83,20 +94,20 @@ public class JingleRtpConnection extends AbstractJingleConnection { } } - private void processContents(final Map contents) { - for(Map.Entry content : contents.entrySet()) { + private void processContents(final Map contents) { + for (Map.Entry content : contents.entrySet()) { final DescriptionTransport descriptionTransport = content.getValue(); final RtpDescription rtpDescription = descriptionTransport.description; - Log.d(Config.LOGTAG,"receive content with name "+content.getKey()+" and media="+rtpDescription.getMedia()); - for(RtpDescription.PayloadType payloadType : rtpDescription.getPayloadTypes()) { - Log.d(Config.LOGTAG,"payload type: "+payloadType.toString()); + Log.d(Config.LOGTAG, "receive content with name " + content.getKey() + " and media=" + rtpDescription.getMedia()); + for (RtpDescription.PayloadType payloadType : rtpDescription.getPayloadTypes()) { + Log.d(Config.LOGTAG, "payload type: " + payloadType.toString()); } - for(RtpDescription.RtpHeaderExtension extension : rtpDescription.getHeaderExtensions()) { - Log.d(Config.LOGTAG,"extension: "+extension.toString()); + for (RtpDescription.RtpHeaderExtension extension : rtpDescription.getHeaderExtensions()) { + Log.d(Config.LOGTAG, "extension: " + extension.toString()); } final IceUdpTransportInfo iceUdpTransportInfo = descriptionTransport.transport; - Log.d(Config.LOGTAG,"transport: "+descriptionTransport.transport); - Log.d(Config.LOGTAG,"fingerprint "+iceUdpTransportInfo.getFingerprint()); + Log.d(Config.LOGTAG, "transport: " + descriptionTransport.transport); + Log.d(Config.LOGTAG, "fingerprint " + iceUdpTransportInfo.getFingerprint()); } } @@ -142,11 +153,12 @@ public class JingleRtpConnection extends AbstractJingleConnection { } private void sendSessionInitiate() { - Log.d(Config.LOGTAG,id.account.getJid().asBareJid()+": sending session-initiate"); + setupWebRTC(); + Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": sending session-initiate"); } private void sendSessionAccept() { - Log.d(Config.LOGTAG,"sending session-accept"); + Log.d(Config.LOGTAG, "sending session-accept"); } public void pickUpCall() { @@ -162,6 +174,110 @@ public class JingleRtpConnection extends AbstractJingleConnection { } } + private void setupWebRTC() { + PeerConnectionFactory.initialize( + PeerConnectionFactory.InitializationOptions.builder(xmppConnectionService).createInitializationOptions() + ); + final PeerConnectionFactory.Options options = new PeerConnectionFactory.Options(); + PeerConnectionFactory peerConnectionFactory = PeerConnectionFactory.builder().createPeerConnectionFactory(); + + final AudioSource audioSource = peerConnectionFactory.createAudioSource(new MediaConstraints()); + + final AudioTrack audioTrack = peerConnectionFactory.createAudioTrack("my-audio-track", audioSource); + final MediaStream stream = peerConnectionFactory.createLocalMediaStream("my-media-stream"); + stream.addTrack(audioTrack); + + + PeerConnection peer = peerConnectionFactory.createPeerConnection(Collections.emptyList(), new PeerConnection.Observer() { + @Override + public void onSignalingChange(PeerConnection.SignalingState signalingState) { + + } + + @Override + public void onIceConnectionChange(PeerConnection.IceConnectionState iceConnectionState) { + + } + + @Override + public void onIceConnectionReceivingChange(boolean b) { + + } + + @Override + public void onIceGatheringChange(PeerConnection.IceGatheringState iceGatheringState) { + + } + + @Override + public void onIceCandidate(IceCandidate iceCandidate) { + + } + + @Override + public void onIceCandidatesRemoved(IceCandidate[] iceCandidates) { + + } + + @Override + public void onAddStream(MediaStream mediaStream) { + + } + + @Override + public void onRemoveStream(MediaStream mediaStream) { + + } + + @Override + public void onDataChannel(DataChannel dataChannel) { + + } + + @Override + public void onRenegotiationNeeded() { + + } + + @Override + public void onAddTrack(RtpReceiver rtpReceiver, MediaStream[] mediaStreams) { + + } + }); + + peer.addStream(stream); + + peer.createOffer(new SdpObserver() { + + @Override + public void onCreateSuccess(org.webrtc.SessionDescription description) { + final SessionDescription sessionDescription = SessionDescription.parse(description.description); + for (SessionDescription.Media media : sessionDescription.media) { + Log.d(Config.LOGTAG, "media: " + media.protocol); + for (SessionDescription.Attribute attribute : media.attributes) { + Log.d(Config.LOGTAG, "attribute key=" + attribute.key + ", value=" + attribute.value); + } + } + Log.d(Config.LOGTAG, sessionDescription.toString()); + } + + @Override + public void onSetSuccess() { + + } + + @Override + public void onCreateFailure(String s) { + + } + + @Override + public void onSetFailure(String s) { + + } + }, new MediaConstraints()); + } + private void pickupCallFromProposed() { transitionOrThrow(State.PROCEED); final MessagePacket messagePacket = new MessagePacket(); @@ -210,7 +326,7 @@ public class JingleRtpConnection extends AbstractJingleConnection { if (description instanceof RtpDescription) { rtpDescription = (RtpDescription) description; } else { - Log.d(Config.LOGTAG,"description was "+description); + Log.d(Config.LOGTAG, "description was " + description); throw new IllegalArgumentException("Content does not contain RtpDescription"); } if (transportInfo instanceof IceUdpTransportInfo) { @@ -221,7 +337,7 @@ public class JingleRtpConnection extends AbstractJingleConnection { return new DescriptionTransport(rtpDescription, iceUdpTransportInfo); } - public static Map of(final Map contents) { + public static Map of(final Map contents) { return ImmutableMap.copyOf(Maps.transformValues(contents, new Function() { @NullableDecl @Override diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java index 2a129b3e8..8054f0a4b 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/SessionDescription.java @@ -11,11 +11,11 @@ import eu.siacs.conversations.Config; public class SessionDescription { - private final int version; - private final String name; - private final String connectionData; - private final List attributes; - private final List media; + public final int version; + public final String name; + public final String connectionData; + public final List attributes; + public final List media; public SessionDescription(int version, String name, String connectionData, List attributes, List media) { @@ -36,10 +36,10 @@ public class SessionDescription { MediaBuilder currentMediaBuilder = null; ImmutableList.Builder attributeBuilder = new ImmutableList.Builder<>(); ImmutableList.Builder mediaBuilder = new ImmutableList.Builder<>(); - for(final String line : input.split("\n")) { - final String[] pair = line.split("=",2); + for (final String line : input.split("\n")) { + final String[] pair = line.split("=", 2); if (pair.length < 2 || pair[0].length() != 1) { - Log.d(Config.LOGTAG,"skipping sdp parsing on line "+line); + Log.d(Config.LOGTAG, "skipping sdp parsing on line " + line); continue; } final char key = pair[0].charAt(0); @@ -63,7 +63,8 @@ public class SessionDescription { break; case 'm': if (currentMediaBuilder == null) { - sessionDescriptionBuilder.setAttributes(attributeBuilder.build());; + sessionDescriptionBuilder.setAttributes(attributeBuilder.build()); + ; } else { currentMediaBuilder.setAttributes(attributeBuilder.build()); mediaBuilder.add(currentMediaBuilder.createMedia()); @@ -76,12 +77,12 @@ public class SessionDescription { currentMediaBuilder.setPort(ignorantIntParser(parts[1])); currentMediaBuilder.setProtocol(parts[2]); ImmutableList.Builder formats = new ImmutableList.Builder<>(); - for(int i = 3; i < parts.length; ++i) { + for (int i = 3; i < parts.length; ++i) { formats.add(ignorantIntParser(parts[i])); } currentMediaBuilder.setFormats(formats.build()); } else { - Log.d(Config.LOGTAG,"skipping media line "+line); + Log.d(Config.LOGTAG, "skipping media line " + line); } break; } @@ -104,8 +105,8 @@ public class SessionDescription { } public static class Attribute { - private final String key; - private final String value; + public final String key; + public final String value; public Attribute(String key, String value) { this.key = key; @@ -113,9 +114,9 @@ public class SessionDescription { } public static Attribute parse(String input) { - final String[] pair = input.split(":",2); + final String[] pair = input.split(":", 2); if (pair.length == 2) { - return new Attribute(pair[0],pair[1]); + return new Attribute(pair[0], pair[1]); } else { return new Attribute(pair[0], null); } @@ -125,12 +126,12 @@ public class SessionDescription { } public static class Media { - private final String media; - private final int port; - private final String protocol; - private final List formats; - private final String connectionData; - private final List attributes; + public final String media; + public final int port; + public final String protocol; + public final List formats; + public final String connectionData; + public final List attributes; public Media(String media, int port, String protocol, List formats, String connectionData, List attributes) { this.media = media; diff --git a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java index 15a208205..8f79022aa 100644 --- a/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java +++ b/src/main/java/eu/siacs/conversations/xmpp/jingle/stanzas/RtpDescription.java @@ -52,6 +52,8 @@ public class RtpDescription extends GenericDescription { //TODO: support for https://xmpp.org/extensions/xep-0293.html + //XEP-0294: Jingle RTP Header Extensions Negotiation + //maps to `extmap:$id $uri` public static class RtpHeaderExtension extends Element { private RtpHeaderExtension() { @@ -76,6 +78,7 @@ public class RtpDescription extends GenericDescription { } } + //maps to `rtpmap $id $name/$clockrate/$channels` public static class PayloadType extends Element { private PayloadType(String name, String xmlns) { @@ -132,6 +135,8 @@ public class RtpDescription extends GenericDescription { } } + //map to `fmtp $id key=value;key=value + //where id is the id of the parent payload-type public static class Parameter extends Element { private Parameter() {