1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-27 00:32:07 +01:00

Payload Negotiation Refactoring and bug fixes

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@7362 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Thiago Camargo 2007-03-03 03:48:59 +00:00 committed by thiago
parent 945561242a
commit 76bd42da26
7 changed files with 109 additions and 61 deletions

View file

@ -43,11 +43,6 @@ public abstract class JingleMediaManager {
*/ */
public abstract List<PayloadType> getPayloads(); public abstract List<PayloadType> getPayloads();
/**
* Get the preferred Payload Type
*/
public abstract PayloadType getPreferredPayloadType();
/** /**
* Create a Media Session Implementation * Create a Media Session Implementation
* *

View file

@ -1,3 +1,22 @@
/**
* $RCSfile$
* $Revision: 7329 $
* $Date: 2007-02-28 20:59:28 -0300 (qua, 28 fev 2007) $
*
* Copyright 2003-2005 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.jingle.media; package org.jivesoftware.smackx.jingle.media;
import org.jivesoftware.smack.XMPPException; import org.jivesoftware.smack.XMPPException;
@ -17,12 +36,13 @@ import java.util.List;
/** /**
* Manager for jmf descriptor negotiation. * Manager for jmf descriptor negotiation.
* * <p/>
* * <p/>
* This class is responsible for managing the descriptor negotiation process, * This class is responsible for managing the descriptor negotiation process,
* handling all the xmpp packets interchange and the stage control. * handling all the xmpp packets interchange and the stage control.
* *
* @author Alvaro Saurin * @author Alvaro Saurin
* @author Thiago Camargo
*/ */
public class MediaNegotiator extends JingleNegotiator { public class MediaNegotiator extends JingleNegotiator {
@ -90,31 +110,37 @@ public class MediaNegotiator extends JingleNegotiator {
// With a null packet, we are just inviting the other end... // With a null packet, we are just inviting the other end...
setState(inviting); setState(inviting);
jout = getState().eventInvite(); jout = getState().eventInvite();
} else { }
else {
if (iq instanceof Jingle) { if (iq instanceof Jingle) {
// If there is no specific jmf action associated, then we // If there is no specific jmf action associated, then we
// are being invited to a new session... // are being invited to a new session...
setState(accepting); setState(accepting);
jout = getState().eventInitiate((Jingle) iq); jout = getState().eventInitiate((Jingle) iq);
} else { }
else {
throw new IllegalStateException( throw new IllegalStateException(
"Invitation IQ received is not a Jingle packet in Media negotiator."); "Invitation IQ received is not a Jingle packet in Media negotiator.");
} }
} }
} else { }
else {
if (iq == null) { if (iq == null) {
return null; return null;
} else { }
else {
if (iq.getType().equals(IQ.Type.ERROR)) { if (iq.getType().equals(IQ.Type.ERROR)) {
// Process errors // Process errors
getState().eventError(iq); getState().eventError(iq);
} else if (iq.getType().equals(IQ.Type.RESULT)) { }
else if (iq.getType().equals(IQ.Type.RESULT)) {
// Process ACKs // Process ACKs
if (isExpectedId(iq.getPacketID())) { if (isExpectedId(iq.getPacketID())) {
jout = getState().eventAck(iq); jout = getState().eventAck(iq);
removeExpectedId(iq.getPacketID()); removeExpectedId(iq.getPacketID());
} }
} else if (iq instanceof Jingle) { }
else if (iq instanceof Jingle) {
// Get the action from the Jingle packet // Get the action from the Jingle packet
Jingle jin = (Jingle) iq; Jingle jin = (Jingle) iq;
Jingle.Action action = jin.getAction(); Jingle.Action action = jin.getAction();
@ -122,11 +148,14 @@ public class MediaNegotiator extends JingleNegotiator {
if (action != null) { if (action != null) {
if (action.equals(Jingle.Action.CONTENTACCEPT)) { if (action.equals(Jingle.Action.CONTENTACCEPT)) {
jout = getState().eventAccept(jin); jout = getState().eventAccept(jin);
} else if (action.equals(Jingle.Action.CONTENTDECLINE)) { }
else if (action.equals(Jingle.Action.CONTENTDECLINE)) {
jout = getState().eventDecline(jin); jout = getState().eventDecline(jin);
} else if (action.equals(Jingle.Action.DESCRIPTIONINFO)) { }
else if (action.equals(Jingle.Action.DESCRIPTIONINFO)) {
jout = getState().eventInfo(jin); jout = getState().eventInfo(jin);
} else if (action.equals(Jingle.Action.CONTENTMODIFY)) { }
else if (action.equals(Jingle.Action.CONTENTMODIFY)) {
jout = getState().eventModify(jin); jout = getState().eventModify(jin);
} }
// Any unknown action will be ignored: it is not a msg // Any unknown action will be ignored: it is not a msg
@ -139,7 +168,8 @@ public class MediaNegotiator extends JingleNegotiator {
// Save the Id for any ACK // Save the Id for any ACK
if (id != null) { if (id != null) {
addExpectedId(id); addExpectedId(id);
} else { }
else {
if (jout != null) { if (jout != null) {
addExpectedId(jout.getPacketID()); addExpectedId(jout.getPacketID());
} }
@ -169,8 +199,8 @@ public class MediaNegotiator extends JingleNegotiator {
// Payload types // Payload types
private PayloadType.Audio calculateBestCommonAudioPt(List remoteAudioPts) { private PayloadType.Audio calculateBestCommonAudioPt(List remoteAudioPts) {
final ArrayList commonAudioPtsHere = new ArrayList(); final ArrayList<PayloadType> commonAudioPtsHere = new ArrayList<PayloadType>();
final ArrayList commonAudioPtsThere = new ArrayList(); final ArrayList<PayloadType> commonAudioPtsThere = new ArrayList<PayloadType>();
PayloadType.Audio result = null; PayloadType.Audio result = null;
if (!remoteAudioPts.isEmpty()) { if (!remoteAudioPts.isEmpty()) {
@ -181,28 +211,30 @@ public class MediaNegotiator extends JingleNegotiator {
commonAudioPtsThere.retainAll(localAudioPts); commonAudioPtsThere.retainAll(localAudioPts);
if (!commonAudioPtsHere.isEmpty() && !commonAudioPtsThere.isEmpty()) { if (!commonAudioPtsHere.isEmpty() && !commonAudioPtsThere.isEmpty()) {
PayloadType.Audio bestPtHere = (PayloadType.Audio) commonAudioPtsHere
.get(0);
PayloadType.Audio bestPtThere = (PayloadType.Audio) commonAudioPtsThere
.get(0);
// If both match, use it PayloadType.Audio bestPtHere = null;
if (bestPtHere.equals(bestPtThere)) {
result = bestPtHere;
} else {
// Otherwise, use the one of the initiator...
// FIXME: this is an invented behavior!!!
String initiator = session.getInitiator();
String me = session.getConnection().getUser();
if (initiator.equals(me)) {
if (bestPtHere == null)
for (PayloadType payloadType : commonAudioPtsHere)
if (payloadType instanceof PayloadType.Audio) {
bestPtHere = (PayloadType.Audio) payloadType;
break;
}
PayloadType.Audio bestPtThere = null;
for (PayloadType payloadType : commonAudioPtsThere)
if (payloadType instanceof PayloadType.Audio) {
bestPtThere = (PayloadType.Audio) payloadType;
break;
}
if (session.getInitiator().equals(session.getConnection().getUser()))
result = bestPtHere; result = bestPtHere;
} else { else
result = bestPtThere; result = bestPtThere;
} }
} }
}
}
return result; return result;
} }
@ -332,6 +364,7 @@ public class MediaNegotiator extends JingleNegotiator {
* First stage when we send a session request. * First stage when we send a session request.
*/ */
public class Inviting extends JingleNegotiator.State { public class Inviting extends JingleNegotiator.State {
public Inviting(MediaNegotiator neg) { public Inviting(MediaNegotiator neg) {
super(neg); super(neg);
} }
@ -391,7 +424,8 @@ public class MediaNegotiator extends JingleNegotiator {
// and send an accept if we havee an agreement... // and send an accept if we havee an agreement...
if (bestCommonAudioPt != null) { if (bestCommonAudioPt != null) {
response = createAcceptMessage(); response = createAcceptMessage();
} else { }
else {
throw new JingleException(JingleError.NO_COMMON_PAYLOAD); throw new JingleException(JingleError.NO_COMMON_PAYLOAD);
} }
@ -407,6 +441,7 @@ public class MediaNegotiator extends JingleNegotiator {
* accepts or not... * accepts or not...
*/ */
public class Pending extends JingleNegotiator.State { public class Pending extends JingleNegotiator.State {
public Pending(MediaNegotiator neg) { public Pending(MediaNegotiator neg) {
super(neg); super(neg);
} }
@ -441,7 +476,8 @@ public class MediaNegotiator extends JingleNegotiator {
if (oldBestCommonAudioPt == null || ptChange) { if (oldBestCommonAudioPt == null || ptChange) {
response = createAcceptMessage(); response = createAcceptMessage();
} }
} else { }
else {
throw new JingleException(JingleError.NO_COMMON_PAYLOAD); throw new JingleException(JingleError.NO_COMMON_PAYLOAD);
} }
} }
@ -481,7 +517,8 @@ public class MediaNegotiator extends JingleNegotiator {
} }
} }
} else if (offeredPayloads.size() > 1) { }
else if (offeredPayloads.size() > 1) {
throw new JingleException(JingleError.MALFORMED_STANZA); throw new JingleException(JingleError.MALFORMED_STANZA);
} }
} }

View file

@ -1,3 +1,23 @@
/**
* $RCSfile$
* $Revision: 7329 $
* $Date: 2007-02-28 20:59:28 -0300 (qua, 28 fev 2007) $
*
* Copyright 2003-2005 Jive Software.
*
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jivesoftware.smackx.packet; package org.jivesoftware.smackx.packet;
import org.jivesoftware.smack.packet.PacketExtension; import org.jivesoftware.smack.packet.PacketExtension;
@ -19,7 +39,7 @@ public class JingleError implements PacketExtension {
// Non standard error messages // Non standard error messages
public static final JingleError NO_COMMON_PAYLOAD = new JingleError( public static final JingleError NO_COMMON_PAYLOAD = new JingleError(
"no-common-payload"); "unsupported-codecs");
public static final JingleError NEGOTIATION_ERROR = new JingleError( public static final JingleError NEGOTIATION_ERROR = new JingleError(
"negotiation-error"); "negotiation-error");
@ -76,7 +96,7 @@ public class JingleError implements PacketExtension {
return UNSUPPORTED_CONTENT; return UNSUPPORTED_CONTENT;
} else if (value.equals("unsupported-transports")) { } else if (value.equals("unsupported-transports")) {
return UNSUPPORTED_TRANSPORTS; return UNSUPPORTED_TRANSPORTS;
} else if (value.equals("no-common-payload")) { } else if (value.equals("unsupported-codecs")) {
return NO_COMMON_PAYLOAD; return NO_COMMON_PAYLOAD;
} else if (value.equals("negotiation-error")) { } else if (value.equals("negotiation-error")) {
return NEGOTIATION_ERROR; return NEGOTIATION_ERROR;

View file

@ -849,7 +849,7 @@ public class JingleManagerTest extends SmackTestCase {
return new ArrayList(); return new ArrayList();
} }
public PayloadType getPreferredPayloadType() { public PayloadType.Audio getPreferredAudioPayloadType() {
return null; return null;
} }

View file

@ -79,14 +79,6 @@ public class JmfMediaManager extends JingleMediaManager {
return payloads; return payloads;
} }
/**
* Get the preferred Payload Type
*/
public PayloadType getPreferredPayloadType() {
//TODO a better way to choose the preferred Payload
return payloads.size() > 0 ? payloads.get(0) : null;
}
/** /**
* Runs JMFInit the first time the application is started so that capture * Runs JMFInit the first time the application is started so that capture
* devices are properly detected and initialized by JMF. * devices are properly detected and initialized by JMF.

View file

@ -66,13 +66,6 @@ public class SpeexMediaManager extends JingleMediaManager {
return payloads; return payloads;
} }
/**
* Get the preferred Payload Type
*/
public PayloadType getPreferredPayloadType() {
return payloads.size() > 0 ? payloads.get(0) : null;
}
/** /**
* Runs JMFInit the first time the application is started so that capture * Runs JMFInit the first time the application is started so that capture
* devices are properly detected and initialized by JMF. * devices are properly detected and initialized by JMF.

View file

@ -15,6 +15,7 @@ import org.jivesoftware.smackx.jingle.media.JingleMediaManager;
import org.jivesoftware.smackx.jingle.nat.BridgedTransportManager; import org.jivesoftware.smackx.jingle.nat.BridgedTransportManager;
import org.jivesoftware.smackx.jingle.nat.ICETransportManager; import org.jivesoftware.smackx.jingle.nat.ICETransportManager;
import org.jivesoftware.smackx.jingle.nat.STUNTransportManager; import org.jivesoftware.smackx.jingle.nat.STUNTransportManager;
import org.jivesoftware.smackx.jingle.nat.BasicTransportManager;
import javax.media.MediaLocator; import javax.media.MediaLocator;
import javax.media.format.AudioFormat; import javax.media.format.AudioFormat;
@ -109,6 +110,7 @@ public class JingleMediaTest extends SmackTestCase {
XMPPConnection x0 = getConnection(0); XMPPConnection x0 = getConnection(0);
XMPPConnection x1 = getConnection(1); XMPPConnection x1 = getConnection(1);
/*
ICETransportManager icetm0 = new ICETransportManager(x0, "jivesoftware.com", 3478); ICETransportManager icetm0 = new ICETransportManager(x0, "jivesoftware.com", 3478);
ICETransportManager icetm1 = new ICETransportManager(x1, "jivesoftware.com", 3478); ICETransportManager icetm1 = new ICETransportManager(x1, "jivesoftware.com", 3478);
@ -119,11 +121,20 @@ public class JingleMediaTest extends SmackTestCase {
jm0.addCreationListener(icetm0); jm0.addCreationListener(icetm0);
jm1.addCreationListener(icetm1); jm1.addCreationListener(icetm1);
*/
final JingleManager jm0 = new JingleManager(
x0, new BasicTransportManager());
final JingleManager jm1 = new JingleManager(
x1, new BasicTransportManager());
MultiMediaManager jingleMediaManager0 = new MultiMediaManager(); MultiMediaManager jingleMediaManager0 = new MultiMediaManager();
jingleMediaManager0.addMediaManager(new SpeexMediaManager()); jingleMediaManager0.addMediaManager(new SpeexMediaManager());
jingleMediaManager0.addMediaManager(new JmfMediaManager()); jingleMediaManager0.addMediaManager(new JmfMediaManager());
JingleMediaManager jingleMediaManager1 = new JmfMediaManager(); jingleMediaManager0.addMediaManager(new JmfMediaManager());
MultiMediaManager jingleMediaManager1 = new MultiMediaManager();
jingleMediaManager1.addMediaManager(new JmfMediaManager());
jingleMediaManager1.addMediaManager(new SpeexMediaManager());
jm0.setMediaManager(jingleMediaManager0); jm0.setMediaManager(jingleMediaManager0);
jm1.setMediaManager(jingleMediaManager1); jm1.setMediaManager(jingleMediaManager1);