create stub objects for most of what’s in description and transport
This commit is contained in:
parent
43cf1783a4
commit
4e13893662
|
@ -38,6 +38,7 @@ public final class Namespace {
|
||||||
public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0";
|
public static final String JINGLE_APPS_DTLS = "urn:xmpp:jingle:apps:dtls:0";
|
||||||
public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio";
|
public static final String JINGLE_FEATURE_AUDIO = "urn:xmpp:jingle:apps:rtp:audio";
|
||||||
public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video";
|
public static final String JINGLE_FEATURE_VIDEO = "urn:xmpp:jingle:apps:rtp:video";
|
||||||
|
public static final String JINGLE_RTP_HEADER_EXTENSIONS = "urn:xmpp:jingle:apps:rtp:rtp-hdrext:0";
|
||||||
public static final String IBB = "http://jabber.org/protocol/ibb";
|
public static final String IBB = "http://jabber.org/protocol/ibb";
|
||||||
public static final String PING = "urn:xmpp:ping";
|
public static final String PING = "urn:xmpp:ping";
|
||||||
public static final String PUSH = "urn:xmpp:push:0";
|
public static final String PUSH = "urn:xmpp:push:0";
|
||||||
|
|
|
@ -73,6 +73,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
final State oldState = this.state;
|
final State oldState = this.state;
|
||||||
if (transition(State.SESSION_INITIALIZED)) {
|
if (transition(State.SESSION_INITIALIZED)) {
|
||||||
if (oldState == State.PROCEED) {
|
if (oldState == State.PROCEED) {
|
||||||
|
processContents(contents);
|
||||||
sendSessionAccept();
|
sendSessionAccept();
|
||||||
} else {
|
} else {
|
||||||
//TODO start ringing
|
//TODO start ringing
|
||||||
|
@ -82,6 +83,23 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void processContents(final Map<String,DescriptionTransport> contents) {
|
||||||
|
for(Map.Entry<String,DescriptionTransport> 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());
|
||||||
|
}
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void deliveryMessage(final Jid from, final Element message) {
|
void deliveryMessage(final Jid from, final Element message) {
|
||||||
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": delivered message to JingleRtpConnection " + message);
|
Log.d(Config.LOGTAG, id.account.getJid().asBareJid() + ": delivered message to JingleRtpConnection " + message);
|
||||||
switch (message.getName()) {
|
switch (message.getName()) {
|
||||||
|
@ -175,7 +193,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DescriptionTransport {
|
public static class DescriptionTransport {
|
||||||
private final RtpDescription description;
|
private final RtpDescription description;
|
||||||
private final IceUdpTransportInfo transport;
|
private final IceUdpTransportInfo transport;
|
||||||
|
|
||||||
|
@ -192,6 +210,7 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
if (description instanceof RtpDescription) {
|
if (description instanceof RtpDescription) {
|
||||||
rtpDescription = (RtpDescription) description;
|
rtpDescription = (RtpDescription) description;
|
||||||
} else {
|
} else {
|
||||||
|
Log.d(Config.LOGTAG,"description was "+description);
|
||||||
throw new IllegalArgumentException("Content does not contain RtpDescription");
|
throw new IllegalArgumentException("Content does not contain RtpDescription");
|
||||||
}
|
}
|
||||||
if (transportInfo instanceof IceUdpTransportInfo) {
|
if (transportInfo instanceof IceUdpTransportInfo) {
|
||||||
|
@ -203,13 +222,13 @@ public class JingleRtpConnection extends AbstractJingleConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<String, DescriptionTransport> of(final Map<String,Content> contents) {
|
public static Map<String, DescriptionTransport> of(final Map<String,Content> contents) {
|
||||||
return Maps.transformValues(contents, new Function<Content, DescriptionTransport>() {
|
return ImmutableMap.copyOf(Maps.transformValues(contents, new Function<Content, DescriptionTransport>() {
|
||||||
@NullableDecl
|
@NullableDecl
|
||||||
@Override
|
@Override
|
||||||
public DescriptionTransport apply(@NullableDecl Content content) {
|
public DescriptionTransport apply(@NullableDecl Content content) {
|
||||||
return content == null ? null : of(content);
|
return content == null ? null : of(content);
|
||||||
}
|
}
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
package eu.siacs.conversations.xmpp.jingle;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SdpUtils {
|
||||||
|
|
||||||
|
public static String toSdpString(Map<String, JingleRtpConnection.DescriptionTransport> contents) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -51,9 +51,11 @@ public class Content extends Element {
|
||||||
if (description == null) {
|
if (description == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String xmlns = description.getNamespace();
|
final String namespace = description.getNamespace();
|
||||||
if (FileTransferDescription.NAMESPACES.contains(xmlns)) {
|
if (FileTransferDescription.NAMESPACES.contains(namespace)) {
|
||||||
return FileTransferDescription.upgrade(description);
|
return FileTransferDescription.upgrade(description);
|
||||||
|
} else if (Namespace.JINGLE_APPS_RTP.equals(namespace)) {
|
||||||
|
return RtpDescription.upgrade(description);
|
||||||
} else {
|
} else {
|
||||||
return GenericDescription.upgrade(description);
|
return GenericDescription.upgrade(description);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
|
@ -11,6 +14,21 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
|
||||||
super(name, xmlns);
|
super(name, xmlns);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Fingerprint getFingerprint() {
|
||||||
|
final Element fingerprint = this.findChild("fingerprint", Namespace.JINGLE_APPS_DTLS);
|
||||||
|
return fingerprint == null ? null : Fingerprint.upgrade(fingerprint);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Candidate> getCandidates() {
|
||||||
|
final ImmutableList.Builder<Candidate> builder = new ImmutableList.Builder<>();
|
||||||
|
for(final Element child : getChildren()) {
|
||||||
|
if ("candidate".equals(child.getName())) {
|
||||||
|
builder.add(Candidate.upgrade(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
public static IceUdpTransportInfo upgrade(final Element element) {
|
public static IceUdpTransportInfo upgrade(final Element element) {
|
||||||
Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
|
Preconditions.checkArgument("transport".equals(element.getName()), "Name of provided element is not transport");
|
||||||
Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
|
Preconditions.checkArgument(Namespace.JINGLE_TRANSPORT_ICE_UDP.equals(element.getNamespace()), "Element does not match ice-udp transport namespace");
|
||||||
|
@ -19,4 +37,104 @@ public class IceUdpTransportInfo extends GenericTransportInfo {
|
||||||
transportInfo.setChildren(element.getChildren());
|
transportInfo.setChildren(element.getChildren());
|
||||||
return transportInfo;
|
return transportInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class Candidate extends Element {
|
||||||
|
|
||||||
|
private Candidate() {
|
||||||
|
super("candidate");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getComponent() {
|
||||||
|
return getAttributeAsInt("component");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFoundation() {
|
||||||
|
return getAttributeAsInt("foundation");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGeneration() {
|
||||||
|
return getAttributeAsInt("generation");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return getAttribute("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return getAttribute("ip");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNetwork() {
|
||||||
|
return getAttributeAsInt("network");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return getAttributeAsInt("port");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return getAttributeAsInt("priority");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProtocol() {
|
||||||
|
return getAttribute("protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRelAddr() {
|
||||||
|
return getAttribute("rel-addr");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRelPort() {
|
||||||
|
return getAttributeAsInt("rel-port");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() { //TODO might be converted to enum
|
||||||
|
return getAttribute("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getAttributeAsInt(final String name) {
|
||||||
|
final String value = this.getAttribute(name);
|
||||||
|
if (value == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Candidate upgrade(final Element element) {
|
||||||
|
Preconditions.checkArgument("candidate".equals(element.getName()));
|
||||||
|
final Candidate candidate = new Candidate();
|
||||||
|
candidate.setAttributes(element.getAttributes());
|
||||||
|
candidate.setChildren(element.getChildren());
|
||||||
|
return candidate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Fingerprint extends Element {
|
||||||
|
|
||||||
|
public String getHash() {
|
||||||
|
return this.getAttribute("hash");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSetup() {
|
||||||
|
return this.getAttribute("setup");
|
||||||
|
}
|
||||||
|
|
||||||
|
private Fingerprint() {
|
||||||
|
super("fingerprint", Namespace.JINGLE_APPS_DTLS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Fingerprint upgrade(final Element element) {
|
||||||
|
Preconditions.checkArgument("fingerprint".equals(element.getName()));
|
||||||
|
Preconditions.checkArgument(Namespace.JINGLE_APPS_DTLS.equals(element.getNamespace()));
|
||||||
|
final Fingerprint fingerprint = new Fingerprint();
|
||||||
|
fingerprint.setAttributes(element.getAttributes());
|
||||||
|
fingerprint.setContent(element.getContent());
|
||||||
|
return fingerprint;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public class JinglePacket extends IqPacket {
|
||||||
return jinglePacket;
|
return jinglePacket;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO can have multiple contents
|
//TODO deprecate this somehow and make file transfer fail if there are multiple (or something)
|
||||||
public Content getJingleContent() {
|
public Content getJingleContent() {
|
||||||
final Element content = getJingleChild("content");
|
final Element content = getJingleChild("content");
|
||||||
return content == null ? null : Content.upgrade(content);
|
return content == null ? null : Content.upgrade(content);
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
package eu.siacs.conversations.xmpp.jingle.stanzas;
|
||||||
|
|
||||||
import com.google.common.base.Preconditions;
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import eu.siacs.conversations.xml.Element;
|
import eu.siacs.conversations.xml.Element;
|
||||||
import eu.siacs.conversations.xml.Namespace;
|
import eu.siacs.conversations.xml.Namespace;
|
||||||
|
@ -12,6 +16,30 @@ public class RtpDescription extends GenericDescription {
|
||||||
super(name, namespace);
|
super(name, namespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Media getMedia() {
|
||||||
|
return Media.of(this.getAttribute("media"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<PayloadType> getPayloadTypes() {
|
||||||
|
final ImmutableList.Builder<PayloadType> builder = new ImmutableList.Builder<>();
|
||||||
|
for(Element child : getChildren()) {
|
||||||
|
if ("payload-type".equals(child.getName())) {
|
||||||
|
builder.add(PayloadType.of(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<RtpHeaderExtension> getHeaderExtensions() {
|
||||||
|
final ImmutableList.Builder<RtpHeaderExtension> builder = new ImmutableList.Builder<>();
|
||||||
|
for(final Element child : getChildren()) {
|
||||||
|
if ("rtp-hdrext".equals(child.getName()) && Namespace.JINGLE_RTP_HEADER_EXTENSIONS.equals(child.getNamespace())) {
|
||||||
|
builder.add(RtpHeaderExtension.upgrade(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
public static RtpDescription upgrade(final Element element) {
|
public static RtpDescription upgrade(final Element element) {
|
||||||
Preconditions.checkArgument("description".equals(element.getName()), "Name of provided element is not description");
|
Preconditions.checkArgument("description".equals(element.getName()), "Name of provided element is not description");
|
||||||
Preconditions.checkArgument(Namespace.JINGLE_APPS_RTP.equals(element.getNamespace()), "Element does not match the jingle rtp namespace");
|
Preconditions.checkArgument(Namespace.JINGLE_APPS_RTP.equals(element.getNamespace()), "Element does not match the jingle rtp namespace");
|
||||||
|
@ -20,4 +48,133 @@ public class RtpDescription extends GenericDescription {
|
||||||
description.setChildren(element.getChildren());
|
description.setChildren(element.getChildren());
|
||||||
return description;
|
return description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO: support for https://xmpp.org/extensions/xep-0293.html
|
||||||
|
|
||||||
|
|
||||||
|
public static class RtpHeaderExtension extends Element {
|
||||||
|
|
||||||
|
private RtpHeaderExtension() {
|
||||||
|
super("rtp-hdrext", Namespace.JINGLE_RTP_HEADER_EXTENSIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return this.getAttribute("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return this.getAttribute("uri");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RtpHeaderExtension upgrade(final Element element) {
|
||||||
|
Preconditions.checkArgument("rtp-hdrext".equals(element.getName()));
|
||||||
|
Preconditions.checkArgument(Namespace.JINGLE_RTP_HEADER_EXTENSIONS.equals(element.getNamespace()));
|
||||||
|
final RtpHeaderExtension extension = new RtpHeaderExtension();
|
||||||
|
extension.setAttributes(element.getAttributes());
|
||||||
|
extension.setChildren(element.getChildren());
|
||||||
|
return extension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PayloadType extends Element {
|
||||||
|
|
||||||
|
private PayloadType(String name, String xmlns) {
|
||||||
|
super(name, xmlns);
|
||||||
|
}
|
||||||
|
public String getId() {
|
||||||
|
return this.getAttribute("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPayloadTypeName() {
|
||||||
|
return this.getAttribute("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getClockRate() {
|
||||||
|
final String clockRate = this.getAttribute("clockrate");
|
||||||
|
if (clockRate == null) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(clockRate);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChannels() {
|
||||||
|
final String channels = this.getAttribute("channels");
|
||||||
|
if (channels == null) {
|
||||||
|
return 1; // The number of channels; if omitted, it MUST be assumed to contain one channel
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(channels);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Parameter> getParameters() {
|
||||||
|
final ImmutableList.Builder<Parameter> builder = new ImmutableList.Builder<>();
|
||||||
|
for (Element child : getChildren()) {
|
||||||
|
if ("parameter".equals(child.getName())) {
|
||||||
|
builder.add(Parameter.of(child));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PayloadType of(final Element element) {
|
||||||
|
Preconditions.checkArgument("payload-type".equals(element.getName()), "element name must be called payload-type");
|
||||||
|
PayloadType payloadType = new PayloadType("payload-type", Namespace.JINGLE_APPS_RTP);
|
||||||
|
payloadType.setAttributes(element.getAttributes());
|
||||||
|
payloadType.setChildren(element.getChildren());
|
||||||
|
return payloadType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Parameter extends Element {
|
||||||
|
|
||||||
|
private Parameter() {
|
||||||
|
super("parameter", Namespace.JINGLE_APPS_RTP);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Parameter(String name, String value) {
|
||||||
|
super("parameter", Namespace.JINGLE_APPS_RTP);
|
||||||
|
this.setAttribute("name", name);
|
||||||
|
this.setAttribute("value", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParameterName() {
|
||||||
|
return this.getAttribute("name");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParameterValue() {
|
||||||
|
return this.getAttribute("value");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Parameter of(final Element element) {
|
||||||
|
Preconditions.checkArgument("parameter".equals(element.getName()), "element name must be called parameter");
|
||||||
|
Parameter parameter = new Parameter();
|
||||||
|
parameter.setAttributes(element.getAttributes());
|
||||||
|
parameter.setChildren(element.getChildren());
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Media {
|
||||||
|
VIDEO, AUDIO, UNKNOWN;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return super.toString().toLowerCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Media of(String value) {
|
||||||
|
try {
|
||||||
|
return value == null ? UNKNOWN : Media.valueOf(value.toUpperCase(Locale.ROOT));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue