diff options
52 files changed, 0 insertions, 12167 deletions
diff --git a/protocols/bundles/org.jivesoftware.smack/jars/jmf.jar b/protocols/bundles/org.jivesoftware.smack/jars/jmf.jar Binary files differdeleted file mode 100644 index ac90e371b..000000000 --- a/protocols/bundles/org.jivesoftware.smack/jars/jmf.jar +++ /dev/null diff --git a/protocols/bundles/org.jivesoftware.smack/jars/jspeex.jar b/protocols/bundles/org.jivesoftware.smack/jars/jspeex.jar Binary files differdeleted file mode 100644 index f7a186152..000000000 --- a/protocols/bundles/org.jivesoftware.smack/jars/jspeex.jar +++ /dev/null diff --git a/protocols/bundles/org.jivesoftware.smack/jars/jstun-0.6.1.jar b/protocols/bundles/org.jivesoftware.smack/jars/jstun-0.6.1.jar Binary files differdeleted file mode 100644 index a37e7b2e7..000000000 --- a/protocols/bundles/org.jivesoftware.smack/jars/jstun-0.6.1.jar +++ /dev/null diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/ContentInfo.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/ContentInfo.java deleted file mode 100644 index d40c772f3..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/ContentInfo.java +++ /dev/null @@ -1,58 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -/** - * Content info. Content info messages are complementary messages that can be - * transmitted for informing of events like "busy", "ringtone", etc. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class ContentInfo { - - /** - * Audio conten info messages. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ - public static class Audio extends ContentInfo { - - public static final ContentInfo.Audio BUSY = new ContentInfo.Audio("busy"); - - public static final ContentInfo.Audio HOLD = new ContentInfo.Audio("hold"); - - public static final ContentInfo.Audio MUTE = new ContentInfo.Audio("mute"); - - public static final ContentInfo.Audio QUEUED = new ContentInfo.Audio("queued"); - - public static final ContentInfo.Audio RINGING = new ContentInfo.Audio("ringing"); - - private String value; - - public Audio(final String value) { - this.value = value; - } - - public String toString() { - return value; - } - - /** - * Returns the MediaInfo constant associated with the String value. - */ - public static ContentInfo fromString(String value) { - value = value.toLowerCase(); - if (value.equals("busy")) { - return BUSY; - } else if (value.equals("hold")) { - return HOLD; - } else if (value.equals("mute")) { - return MUTE; - } else if (value.equals("queued")) { - return QUEUED; - } else if (value.equals("ringing")) { - return RINGING; - } else { - return null; - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/IncomingJingleSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/IncomingJingleSession.java deleted file mode 100644 index 30a400c26..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/IncomingJingleSession.java +++ /dev/null @@ -1,365 +0,0 @@ -/** - * $RCSfile: IncomingJingleSession.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:12:42 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.jingle; - -import java.util.List; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleError; -import org.jivesoftware.smackx.packet.JingleContentDescription.JinglePayloadType; - -/** - * An incoming Jingle session. - * - * </p> - * - * This class is not directly used by users. Instead, users should refer to the - * JingleManager class, that will create the appropiate instance... - * - * </p> - * - * @author Alvaro Saurin - */ -public class IncomingJingleSession extends JingleSession { - - // states - private final Accepting accepting; - - private final Pending pending; - - private final Active active; - - /** - * Constructor with the request - * - * @param conn the XMPP connection - * @param responder the responder - * @param resolver The transport resolver - */ - public IncomingJingleSession(final XMPPConnection conn, final String responder, - final List payloadTypes, final TransportResolver resolver) { - - super(conn, responder, conn.getUser()); - - // Create the states... - - accepting = new Accepting(this); - pending = new Pending(this); - active = new Active(this); - - setMediaNeg(new MediaNegotiator(this, payloadTypes)); - setTransportNeg(new TransportNegotiator.RawUdp(this, resolver)); - } - - /** - * Start the session. - * - * @throws XMPPException - */ - public void start(final JingleSessionRequest request) throws XMPPException { - if (invalidState()) { - Jingle jin = request.getJingle(); - if (jin != null) { - - // Initialize the session information - setSid(jin.getSid()); - - // Establish the default state - setState(accepting); - - updatePacketListener(); - respond(jin); - } else { - throw new IllegalStateException( - "Session request with null Jingle packet."); - } - } else { - throw new IllegalStateException("Starting session without null state."); - } - } - - // States - - /** - * First stage when we have received a session request, and we accept the - * request. We start in this stage, as the instance is created when the user - * accepts the connection... - */ - public class Accepting extends JingleNegotiator.State { - - public Accepting(final JingleNegotiator neg) { - super(neg); - } - - /** - * Initiate the incoming session. We have already sent the ACK partially - * accepting the session... - * - * @throws XMPPException - */ - public Jingle eventInitiate(final Jingle inJingle) throws XMPPException { - // Set the new session state - setState(pending); - return super.eventInitiate(inJingle); - } - - /** - * An error has occurred. - * - * @throws XMPPException - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionClosedOnError(new JingleException(iq.getError().getMessage())); - super.eventError(iq); - } - } - - /** - * "Pending" state: we are waiting for the transport and content - * negotiators. - */ - private class Pending extends JingleNegotiator.State { - - JingleListener.Media mediaListener; - - JingleListener.Transport transportListener; - - public Pending(final JingleNegotiator neg) { - super(neg); - - // Create the listeners that will send a "session-accept" when the - // sub-negotiators are done. - mediaListener = new JingleListener.Media() { - public void mediaClosed(final PayloadType cand) { - } - - public void mediaEstablished(final PayloadType pt) { - checkFullyEstablished(); - } - }; - - transportListener = new JingleListener.Transport() { - public void transportEstablished(final TransportCandidate local, - final TransportCandidate remote) { - checkFullyEstablished(); - } - - public void transportClosed(final TransportCandidate cand) { - } - - public void transportClosedOnError(final XMPPException e) { - } - }; - } - - /** - * Enter in the pending state: wait for the sub-negotiators. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - // Add the listeners to the sub-negotiators... - addMediaListener(mediaListener); - addTransportListener(transportListener); - super.eventEnter(); - } - - /** - * Exit of the state - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventExit() - */ - public void eventExit() { - removeMediaListener(mediaListener); - removeTransportListener(transportListener); - super.eventExit(); - } - - /** - * Check if the session has been fully accepted by all the - * sub-negotiators and, in that case, send an "accept" message... - */ - private void checkFullyEstablished() { - if (isFullyEstablished()) { - - PayloadType.Audio bestCommonAudioPt = getMediaNeg() - .getBestCommonAudioPt(); - TransportCandidate bestRemoteCandidate = getTransportNeg() - .getBestRemoteCandidate(); - TransportCandidate acceptedLocalCandidate = getTransportNeg() - .getAcceptedLocalCandidate(); - - if (bestCommonAudioPt != null && bestRemoteCandidate != null - && acceptedLocalCandidate != null) { - // Ok, send a packet saying that we accept this session - Jingle jout = new Jingle(Jingle.Action.SESSIONACCEPT); - - // ... with the audio payload type and the transport - // candidate - jout.addDescription(new JingleContentDescription.Audio( - new JinglePayloadType(bestCommonAudioPt))); - jout.addTransport(getTransportNeg().getJingleTransport( - bestRemoteCandidate)); - - addExpectedId(jout.getPacketID()); - sendFormattedJingle(jout); - } - } - } - - /** - * The other endpoint has accepted the session. - */ - public Jingle eventAccept(final Jingle jin) throws XMPPException { - - PayloadType acceptedPayloadType = null; - TransportCandidate acceptedLocalCandidate = null; - - // We process the "accepted" if we have finished the - // sub-negotiators. Maybe this is not needed (ie, the other endpoint - // can take the first valid transport candidate), but otherwise we - // must cancel the negotiators... - // - if (isFullyEstablished()) { - acceptedPayloadType = getAcceptedAudioPayloadType(jin); - acceptedLocalCandidate = getAcceptedLocalCandidate(jin); - - if (acceptedPayloadType != null && acceptedLocalCandidate != null) { - if (acceptedPayloadType.equals(getMediaNeg().getBestCommonAudioPt()) - && acceptedLocalCandidate.equals(getTransportNeg() - .getAcceptedLocalCandidate())) { - setState(active); - } - } else { - throw new JingleException(JingleError.MALFORMED_STANZA); - } - } - - return super.eventAccept(jin); - } - - /** - * We have received a confirmation. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) throws XMPPException { - setState(active); - return super.eventAck(iq); - } - - /** - * An error has occurred. - * - * @throws XMPPException - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionClosedOnError(new XMPPException(iq.getError().getMessage())); - super.eventError(iq); - } - } - - /** - * "Active" state: we have an agreement about the session. - */ - private class Active extends JingleNegotiator.State { - public Active(final JingleNegotiator neg) { - super(neg); - } - - /** - * We have a established session: notify the listeners - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - PayloadType.Audio bestCommonAudioPt = getMediaNeg().getBestCommonAudioPt(); - TransportCandidate bestRemoteCandidate = getTransportNeg() - .getBestRemoteCandidate(); - TransportCandidate acceptedLocalCandidate = getTransportNeg() - .getAcceptedLocalCandidate(); - - // Trigger the session established flag - triggerSessionEstablished(bestCommonAudioPt, bestRemoteCandidate, - acceptedLocalCandidate); - - super.eventEnter(); - } - - /** - * Terminate the connection. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventTerminate(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventTerminate(final Jingle jin) throws XMPPException { - triggerSessionClosed(null); - return super.eventTerminate(jin); - } - - /** - * An error has occurred. - * - * @throws XMPPException - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionClosedOnError(new XMPPException(iq.getError().getMessage())); - super.eventError(iq); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleListener.java deleted file mode 100644 index 621435124..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleListener.java +++ /dev/null @@ -1,164 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.nat.TransportCandidate; - -/** - * Jingle listeners. - * - * </p> - * - * This is the list of events that can be observed from a JingleSession and some - * sub negotiators. This listeners can be added to different elements of the - * Jingle model. - * - * </p> - * - * For example, a JingleManager can notify any JingleListener.SessionRequest - * listener when a new session request is received. In this case, the - * <i>sessionRequested()</i> of the listener will be executed, and the listener - * will be able to <i>accept()</i> or <i>decline()</i> the invitation. - * - * </p> - * - * @author Alvaro Saurin - */ -public interface JingleListener { - - /** - * Jingle session request listener. - * - * @author Alvaro Saurin - */ - public static interface SessionRequest extends JingleListener { - /** - * A request to start a session has been recieved from another user. - * - * @param request The request from the other user. - */ - public void sessionRequested(final JingleSessionRequest request); - } - - /** - * Interface for listening for session events. - */ - public static interface Session extends JingleListener { - /** - * Notification that the session has been established. Arguments specify - * the payload type and transport to use. - * - * @param pt The Payload tyep to use - * @param rc The remote candidate to use for connecting to the remote - * service. - * @param lc The local candidate where we must listen for connections - */ - public void sessionEstablished(final PayloadType pt, final TransportCandidate rc, - final TransportCandidate lc); - - /** - * Notification that the session was declined. - * - * @param reason The reason (if any). - */ - public void sessionDeclined(final String reason); - - /** - * Notification that the session was redirected. - */ - public void sessionRedirected(final String redirection); - - /** - * Notification that the session was closed normally. - * - * @param reason The reason (if any). - */ - public void sessionClosed(final String reason); - - /** - * Notification that the session was closed due to an exception. - * - * @param e the exception. - */ - public void sessionClosedOnError(final XMPPException e); - } - - /** - * Interface for listening to transport events. - */ - public static interface Transport extends JingleListener { - /** - * Notification that the transport has been established. - * - * @param local The transport candidate that has been used for listening - * in the local machine - * @param remote The transport candidate that has been used for - * transmitting to the remote machine - */ - public void transportEstablished(final TransportCandidate local, - final TransportCandidate remote); - - /** - * Notification that a transport must be cancelled. - * - * @param cand The transport candidate that must be cancelled. A value - * of "null" means all the transports for this session. - */ - public void transportClosed(final TransportCandidate cand); - - /** - * Notification that the transport was closed due to an exception. - * - * @param e the exception. - */ - public void transportClosedOnError(final XMPPException e); - } - - /** - * Interface for listening to media events. - */ - public static interface Media extends JingleListener { - /** - * Notification that the media has been negotiated and established. - * - * @param pt The payload type agreed. - */ - public void mediaEstablished(final PayloadType pt); - - /** - * Notification that a payload type must be cancelled - * - * @param cand The payload type that must be closed - */ - public void mediaClosed(final PayloadType cand); - } - - /** - * Interface for listening to media info events. - */ - public static interface MediaInfo extends JingleListener { - /** - * The other end is busy. - */ - public void mediaInfoBusy(); - - /** - * We are on hold. - */ - public void mediaInfoHold(); - - /** - * The media is muted. - */ - public void mediaInfoMute(); - - /** - * We are queued. - */ - public void mediaInfoQueued(); - - /** - * We are ringing. - */ - public void mediaInfoRinging(); - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManager.java deleted file mode 100644 index 49bf6fa41..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManager.java +++ /dev/null @@ -1,363 +0,0 @@ -/** - * $RCSfile: JingleManager.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:12:42 $ - * - * 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; - -import java.util.ArrayList; -import java.util.List; - -import org.jivesoftware.smack.ConnectionEstablishedListener; -import org.jivesoftware.smack.PacketListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.PacketFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.util.StringUtils; -import org.jivesoftware.smackx.ServiceDiscoveryManager; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.packet.DiscoverInfo; -import org.jivesoftware.smackx.packet.Jingle; - -/** - * The JingleManager is a facade built upon Jabber Jingle (JEP-166) to allow the - * use of the Jingle extension. This implementation allows the user to simply - * use this class for setting the Jingle parameters. - * - * </p> - * - * This is an example of how to use the Jingle code: - * - * <pre> - * XMPPConnection con = new XMPPConnection("jabber.org"); - * - * TransportResolver tm = new STUNResolver(); - * - * JingleManager jmanager = new JingleManager(conn, tm); - * - * // Insert the payloads in the "mypayloads" list... - * - * OutgoingJingleSession jsession = jmanager.createOutgoingJingleSession(mypayloads); - * - * // Install some session listeners... - * - * </pre> - * - * In order to use the Jingle extension, the user must provide a - * TransportResolver that will handle the resolution of the external address of - * the machine. This resolver can be initialized with several default resolvers, - * including a fixed solver that can be used when the address and port are know - * in advance. See TransportResolver or TransportManager for a complete list of - * resolution services. - * - * </p> - * - * Before creating an outgoing connection, the user must create session - * listeners that will be called when different events happen. The most - * important event is <i>sessionEstablished()</i>, that will be called when all - * the negotiations are finished, providing the payload type for the - * transmission as well as the remote and local addresses and ports for the - * communication. See JingleListener for a complete list of events that can be - * observed. - * - * </p> - * - * @see JingleListener - * @see TransportResolver - * @see TransportManager - * @see OutgoingJingleSession - * @see IncomingJingleSession - * - * </p> - * @author Alvaro Saurin - */ -public class JingleManager { - - // non-static - - // Listeners for manager events (ie, session requests...) - private List listeners; - - // The XMPP connection - private XMPPConnection connection; - - // The Jingle transport manager - private final TransportResolver resolver; - - static { - ProviderManager.addIQProvider("jingle", "http://jabber.org/protocol/jingle", - new org.jivesoftware.smackx.provider.JingleProvider()); - - ProviderManager.addExtensionProvider("description", "http://jabber.org/protocol/jingle/description/audio", - new org.jivesoftware.smackx.provider.JingleContentDescriptionProvider.Audio()); - - ProviderManager.addExtensionProvider("transport", "http://jabber.org/protocol/jingle/transport/ice", - new org.jivesoftware.smackx.provider.JingleTransportProvider.Ice()); - ProviderManager.addExtensionProvider("transport", "http://jabber.org/protocol/jingle/transport/raw-udp", - new org.jivesoftware.smackx.provider.JingleTransportProvider.RawUdp()); - - ProviderManager.addExtensionProvider("busy", "http://jabber.org/protocol/jingle/info/audio", - new org.jivesoftware.smackx.provider.JingleContentInfoProvider.Audio.Busy()); - ProviderManager.addExtensionProvider("hold", "http://jabber.org/protocol/jingle/info/audio", - new org.jivesoftware.smackx.provider.JingleContentInfoProvider.Audio.Hold()); - ProviderManager.addExtensionProvider("mute", "http://jabber.org/protocol/jingle/info/audio", - new org.jivesoftware.smackx.provider.JingleContentInfoProvider.Audio.Mute()); - ProviderManager.addExtensionProvider("queued", "http://jabber.org/protocol/jingle/info/audio", - new org.jivesoftware.smackx.provider.JingleContentInfoProvider.Audio.Queued()); - ProviderManager.addExtensionProvider("ringing", "http://jabber.org/protocol/jingle/info/audio", - new org.jivesoftware.smackx.provider.JingleContentInfoProvider.Audio.Ringing()); - - - // Enable the Jingle support on every established connection - // The ServiceDiscoveryManager class should have been already - // initialized - XMPPConnection.addConnectionListener(new ConnectionEstablishedListener() { - public void connectionEstablished(final XMPPConnection connection) { - JingleManager.setServiceEnabled(connection, true); - } - }); - } - - /** - * Private constructor - */ - private JingleManager() { - resolver = null; - } - - /** - * Default constructor, with a connection. - * - * @param conn - */ - public JingleManager(final XMPPConnection conn, final TransportResolver res) { - connection = conn; - resolver = res; - } - - /** - * Enables or disables the Jingle support on a given connection. - * <p> - * - * Before starting any Jingle media session, check that the user can handle - * it. Enable the Jingle support to indicate that this client handles Jingle - * messages. - * - * @param connection the connection where the service will be enabled or - * disabled - * @param enabled indicates if the service will be enabled or disabled - */ - public synchronized static void setServiceEnabled(final XMPPConnection connection, - final boolean enabled) { - if (isServiceEnabled(connection) == enabled) { - return; - } - - if (enabled) { - ServiceDiscoveryManager.getInstanceFor(connection).addFeature( - Jingle.NAMESPACE); - } else { - ServiceDiscoveryManager.getInstanceFor(connection).removeFeature( - Jingle.NAMESPACE); - } - } - - /** - * Returns true if the Jingle support is enabled for the given connection. - * - * @param connection the connection to look for Jingle support - * @return a boolean indicating if the Jingle support is enabled for the - * given connection - */ - public static boolean isServiceEnabled(final XMPPConnection connection) { - return ServiceDiscoveryManager.getInstanceFor(connection).includesFeature( - Jingle.NAMESPACE); - } - - /** - * Returns true if the specified user handles Jingle messages. - * - * @param connection the connection to use to perform the service discovery - * @param userID the user to check. A fully qualified xmpp ID, e.g. - * jdoe@example.com - * @return a boolean indicating whether the specified user handles Jingle - * messages - */ - public static boolean isServiceEnabled(final XMPPConnection connection, - final String userID) { - try { - DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection) - .discoverInfo(userID); - return result.containsFeature(Jingle.NAMESPACE); - } catch (XMPPException e) { - e.printStackTrace(); - return false; - } - } - - /** - * Add a Jingle session request listener to listen to incoming session - * requests. - * - * @param li The listener - * - * @see #removeJingleSessionRequestListener(JingleListener.SessionRequest) - * @see JingleListener - */ - public synchronized void addJingleSessionRequestListener( - final JingleListener.SessionRequest li) { - if (li != null) { - if (listeners == null) { - initJingleSessionRequestListeners(); - } - synchronized (listeners) { - listeners.add(li); - } - } - } - - /** - * Removes a Jingle session listener. - * - * @param li The jingle session listener to be removed - * @see #addJingleSessionRequestListener(JingleListener.SessionRequest) - * @see JingleListener - */ - public void removeJingleSessionRequestListener(final JingleListener.SessionRequest li) { - if (listeners == null) { - return; - } - synchronized (listeners) { - listeners.remove(li); - } - } - - /** - * Register the listeners, waiting for a Jingle packet that tries to - * establish a new session. - */ - private void initJingleSessionRequestListeners() { - PacketFilter initRequestFilter = new PacketFilter() { - // Return true if we accept this packet - public boolean accept(Packet pin) { - if (pin instanceof IQ) { - IQ iq = (IQ) pin; - if (iq.getType().equals(IQ.Type.SET)) { - if (iq instanceof Jingle) { - Jingle jin = (Jingle) pin; - if (jin.getAction().equals(Jingle.Action.SESSIONINITIATE)) { - return true; - } - } - } - } - return false; - } - }; - - listeners = new ArrayList(); - - // Start a packet listener for session initiation requests - connection.addPacketListener(new PacketListener() { - public void processPacket(final Packet packet) { - triggerSessionRequested((Jingle) packet); - } - }, initRequestFilter); - } - - /** - * Activates the listeners on a Jingle session request. - * - * @param initJin The packet that must be passed to the listeners. - */ - protected void triggerSessionRequested(final Jingle initJin) { - JingleListener.SessionRequest[] listeners = null; - - // Make a synchronized copy of the listeners - synchronized (this.listeners) { - listeners = new JingleListener.SessionRequest[this.listeners.size()]; - this.listeners.toArray(listeners); - } - - // ... and let them know of the event - JingleSessionRequest request = new JingleSessionRequest(this, initJin); - for (int i = 0; i < listeners.length; i++) { - listeners[i].sessionRequested(request); - } - } - - // Session creation - - /** - * Creates an Jingle session to start a communication with another user. - * - * @param responder The fully qualified jabber ID with resource of the other - * user. - * @return The session on which the negotiation can be run. - */ - public OutgoingJingleSession createOutgoingJingleSession(final String responder, - final List payloadTypes) { - - if (responder == null || StringUtils.parseName(responder).length() <= 0 - || StringUtils.parseServer(responder).length() <= 0 - || StringUtils.parseResource(responder).length() <= 0) { - throw new IllegalArgumentException( - "The provided user id was not fully qualified"); - } - - OutgoingJingleSession session = new OutgoingJingleSession(connection, responder, - payloadTypes, resolver); - return session; - } - - /** - * When the session request is acceptable, this method should be invoked. It - * will create an JingleSession which allows the negotiation to procede. - * - * @param request The remote request that is being accepted. - * @return The session which manages the rest of the negotiation. - */ - public IncomingJingleSession createIncomingJingleSession( - final JingleSessionRequest request, final List payloadTypes) { - if (request == null) { - throw new NullPointerException("Received request cannot be null"); - } - - IncomingJingleSession session = new IncomingJingleSession(connection, request - .getFrom(), payloadTypes, resolver); - - return session; - } - - /** - * Reject the session. If we don't want to accept the new session, send an - * appropriate error packet. - * - * @param request the request. - */ - protected void rejectIncomingJingleSession(final JingleSessionRequest request) { - Jingle initiation = request.getJingle(); - - IQ rejection = JingleSession.createError(initiation.getPacketID(), initiation - .getFrom(), initiation.getTo(), 403, "Declined"); - connection.sendPacket(rejection); - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManagerTest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManagerTest.java deleted file mode 100644 index 277ac2258..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleManagerTest.java +++ /dev/null @@ -1,662 +0,0 @@ -/** - * $RCSfile: JingleManagerTest.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:12:42 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.jingle; - -import java.util.ArrayList; - -import org.jivesoftware.smack.PacketListener; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.PacketFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.test.SmackTestCase; -import org.jivesoftware.smackx.nat.FixedResolver; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.packet.Jingle; - -/** - * Test the Jingle extension using the high level API - * </p> - * - * @author Alvaro Saurin - */ -public class JingleManagerTest extends SmackTestCase { - - private int counter; - - private final Object mutex = new Object(); - - /** - * Constructor for JingleManagerTest. - * - * @param name - */ - public JingleManagerTest(final String name) { - super(name); - - resetCounter(); - } - - // Counter management - - private void resetCounter() { - synchronized (mutex) { - counter = 0; - } - } - - private void incCounter() { - synchronized (mutex) { - counter++; - } - } - - private int valCounter() { - int val; - synchronized (mutex) { - val = counter; - } - return val; - } - - /** - * Generate a list of payload types - * - * @return A testing list - */ - private ArrayList getTestPayloads1() { - ArrayList result = new ArrayList(); - - result.add(new PayloadType.Audio(34, "supercodec-1", 2, 14000)); - result.add(new PayloadType.Audio(56, "supercodec-2", 1, 44000)); - result.add(new PayloadType.Audio(36, "supercodec-3", 2, 28000)); - result.add(new PayloadType.Audio(45, "supercodec-4", 1, 98000)); - - return result; - } - - private ArrayList getTestPayloads2() { - ArrayList result = new ArrayList(); - - result.add(new PayloadType.Audio(27, "supercodec-3", 2, 28000)); - result.add(new PayloadType.Audio(56, "supercodec-2", 1, 44000)); - result.add(new PayloadType.Audio(32, "supercodec-4", 1, 98000)); - result.add(new PayloadType.Audio(34, "supercodec-1", 2, 14000)); - - return result; - } - - private ArrayList getTestPayloads3() { - ArrayList result = new ArrayList(); - - result.add(new PayloadType.Audio(91, "badcodec-1", 2, 28000)); - result.add(new PayloadType.Audio(92, "badcodec-2", 1, 44000)); - result.add(new PayloadType.Audio(93, "badcodec-3", 1, 98000)); - result.add(new PayloadType.Audio(94, "badcodec-4", 2, 14000)); - - return result; - } - - /** - * Test for the session request detection. Here, we use the same filter we - * use in the JingleManager... - */ - public void testInitJingleSessionRequestListeners() { - - resetCounter(); - - PacketFilter initRequestFilter = new PacketFilter() { - // Return true if we accept this packet - public boolean accept(Packet pin) { - if (pin instanceof IQ) { - IQ iq = (IQ) pin; - if (iq.getType().equals(IQ.Type.SET)) { - if (iq instanceof Jingle) { - Jingle jin = (Jingle) pin; - if (jin.getAction().equals(Jingle.Action.SESSIONINITIATE)) { - System.out - .println("Session initiation packet accepted... "); - return true; - } - } - } - } - return false; - } - }; - - // Start a packet listener for session initiation requests - getConnection(0).addPacketListener(new PacketListener() { - public void processPacket(final Packet packet) { - System.out.println("Packet detected... "); - incCounter(); - } - }, initRequestFilter); - - // Create a dummy packet for testing... - IQfake iqSent = new IQfake( - " <jingle xmlns='http://jabber.org/protocol/jingle'" - + " initiator=\"gorrino@viejo.com\"" - + " responder=\"colico@hepatico.com\"" - + " action=\"session-initiate\" sid=\"08666555\">" - + " <description xmlns='http://jabber.org/protocol/jingle/content/audio'>" - + " <payload-type id=\"34\" name=\"supercodec-34\"/>" - + " <payload-type id=\"23\" name=\"supercodec-23\"/>" - + " </description>" - + " <transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>" - + " <candidate generation=\"1\"" + " ip=\"192.168.1.1\"" - + " password=\"secret\"" + " port=\"8080\"" - + " username=\"username\"" + " preference=\"1\"/>" - + " </transport>" + "</jingle>"); - - iqSent.setTo(getFullJID(0)); - iqSent.setFrom(getFullJID(0)); - iqSent.setType(IQ.Type.SET); - - System.out.println("Sending packet and waiting... "); - getConnection(0).sendPacket(iqSent); - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - } - - System.out.println("Awake... "); - assertTrue(valCounter() > 0); - } - - /** - * High level API test. This is a simple test to use with a XMPP client and - * check if the client receives the message 1. User_1 will send an - * invitation to user_2. - */ - public void testSendSimpleMessage() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54222); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54567); - - JingleManager man0 = new JingleManager(getConnection(0), tr1); - JingleManager man1 = new JingleManager(getConnection(1), tr2); - - // Session 1 waits for connections - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - incCounter(); - System.out.println("Session request detected, from " - + request.getFrom()); - } - }); - - // Session 0 starts a request - System.out.println("Starting session request, to " + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - session0.start(null); - - Thread.sleep(5000); - - assertTrue(valCounter() > 0); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - /** - * High level API test. This is a simple test to use with a XMPP client and - * check if the client receives the message 1. User_1 will send an - * invitation to user_2. - */ - public void testAcceptJingleSession() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54222); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54567); - - final JingleManager man0 = new JingleManager(getConnection(0), tr1); - final JingleManager man1 = new JingleManager(getConnection(1), tr2); - - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - incCounter(); - System.out.println("Session request detected, from " - + request.getFrom() + ": accepting."); - - // We accept the request - IncomingJingleSession session1 = request.accept(getTestPayloads2()); - try { - session1.start(request); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - // Session 0 starts a request - System.out.println("Starting session request, to " + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - session0.start(null); - - Thread.sleep(20000); - - assertTrue(valCounter() > 0); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - /** - * This is a simple test where both endpoints have exactly the same payloads - * and the session is accepted. - */ - public void testEqualPayloadsSetSession() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54213); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54531); - - final JingleManager man0 = new JingleManager(getConnection(0), tr1); - final JingleManager man1 = new JingleManager(getConnection(1), tr2); - - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - System.out.println("Session request detected, from " - + request.getFrom() + ": accepting."); - - // We accept the request - IncomingJingleSession session1 = request.accept(getTestPayloads1()); - - session1.addListener(new JingleListener.Session() { - public void sessionClosed(final String reason) { - System.out.println("sessionClosed()."); - } - - public void sessionClosedOnError(final XMPPException e) { - System.out.println("sessionClosedOnError()."); - } - - public void sessionDeclined(final String reason) { - System.out.println("sessionDeclined()."); - } - - public void sessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - incCounter(); - System.out - .println("Responder: the session is fully established."); - System.out.println("+ Payload Type: " + pt.getId()); - System.out.println("+ Local IP/port: " + lc.getIP() + ":" - + lc.getPort()); - System.out.println("+ Remote IP/port: " + rc.getIP() + ":" - + rc.getPort()); - } - - public void sessionRedirected(final String redirection) { - } - }); - - try { - session1.start(request); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - // Session 0 starts a request - System.out.println("Starting session request with equal payloads, to " - + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - session0.start(null); - - Thread.sleep(20000); - - assertTrue(valCounter() == 2); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - /** - * This is a simple test where the user_2 rejects the Jingle session. - * - */ - public void testStagesSession() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54222); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54567); - - final JingleManager man0 = new JingleManager(getConnection(0), tr1); - final JingleManager man1 = new JingleManager(getConnection(1), tr2); - - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - System.out.println("Session request detected, from " - + request.getFrom() + ": accepting."); - - // We accept the request - IncomingJingleSession session1 = request.accept(getTestPayloads2()); - - session1.addListener(new JingleListener.Session() { - public void sessionClosed(final String reason) { - System.out.println("sessionClosed()."); - } - - public void sessionClosedOnError(final XMPPException e) { - System.out.println("sessionClosedOnError()."); - } - - public void sessionDeclined(final String reason) { - System.out.println("sessionDeclined()."); - } - - public void sessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - incCounter(); - System.out - .println("Responder: the session is fully established."); - System.out.println("+ Payload Type: " + pt.getId()); - System.out.println("+ Local IP/port: " + lc.getIP() + ":" - + lc.getPort()); - System.out.println("+ Remote IP/port: " + rc.getIP() + ":" - + rc.getPort()); - } - - public void sessionRedirected(final String redirection) { - } - }); - - try { - session1.start(request); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - // Session 0 starts a request - System.out.println("Starting session request, to " + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - - session0.addListener(new JingleListener.Session() { - public void sessionClosed(final String reason) { - } - - public void sessionClosedOnError(final XMPPException e) { - } - - public void sessionDeclined(final String reason) { - } - - public void sessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - incCounter(); - System.out.println("Initiator: the session is fully established."); - System.out.println("+ Payload Type: " + pt.getId()); - System.out.println("+ Local IP/port: " + lc.getIP() + ":" - + lc.getPort()); - System.out.println("+ Remote IP/port: " + rc.getIP() + ":" - + rc.getPort()); - } - - public void sessionRedirected(final String redirection) { - } - }); - session0.start(null); - - Thread.sleep(20000); - - assertTrue(valCounter() == 2); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - /** - * This is a simple test where the user_2 rejects the Jingle session. - */ - public void testRejectSession() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54222); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54567); - - final JingleManager man0 = new JingleManager(getConnection(0), tr1); - final JingleManager man1 = new JingleManager(getConnection(1), tr2); - - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - System.out.println("Session request detected, from " - + request.getFrom() + ": rejecting."); - - // We reject the request - request.reject(); - } - }); - - // Session 0 starts a request - System.out.println("Starting session request, to " + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - - session0.addListener(new JingleListener.Session() { - public void sessionClosed(final String reason) { - } - - public void sessionClosedOnError(final XMPPException e) { - } - - public void sessionDeclined(final String reason) { - incCounter(); - System.out - .println("The session has been detected as rejected with reason: " - + reason); - } - - public void sessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - } - - public void sessionRedirected(final String redirection) { - } - }); - - session0.start(null); - - Thread.sleep(20000); - - assertTrue(valCounter() > 0); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - /** - * This is a simple test where the user_2 rejects the Jingle session. - */ - public void testIncompatibleCodecs() { - - resetCounter(); - - try { - TransportResolver tr1 = new FixedResolver("127.0.0.1", 54222); - TransportResolver tr2 = new FixedResolver("127.0.0.1", 54567); - - final JingleManager man0 = new JingleManager(getConnection(0), tr1); - final JingleManager man1 = new JingleManager(getConnection(1), tr2); - - man1.addJingleSessionRequestListener(new JingleListener.SessionRequest() { - /** - * Called when a new session request is detected - */ - public void sessionRequested(final JingleSessionRequest request) { - System.out.println("Session request detected, from " - + request.getFrom() + ": accepting."); - - // We reject the request - IncomingJingleSession ses = request.accept(getTestPayloads3()); - try { - ses.start(request); - } catch (Exception e) { - e.printStackTrace(); - } - } - }); - - // Session 0 starts a request - System.out.println("Starting session request, to " + getFullJID(1) + "..."); - OutgoingJingleSession session0 = man0.createOutgoingJingleSession( - getFullJID(1), getTestPayloads1()); - - session0.addListener(new JingleListener.Session() { - public void sessionClosed(final String reason) { - } - - public void sessionClosedOnError(final XMPPException e) { - incCounter(); - System.out - .println("The session has been close on error with reason: " - + e.getMessage()); - } - - public void sessionDeclined(final String reason) { - incCounter(); - System.out - .println("The session has been detected as rejected with reason: " - + reason); - } - - public void sessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - } - - public void sessionRedirected(final String redirection) { - } - }); - - session0.start(null); - - Thread.sleep(20000); - - assertTrue(valCounter() > 0); - - } catch (Exception e) { - e.printStackTrace(); - fail("An error occured with Jingle"); - } - } - - protected int getMaxConnections() { - return 2; - } - - /** - * Simple class for testing an IQ... - * - * @author Alvaro Saurin - */ - private class IQfake extends IQ { - private String s; - - public IQfake(final String s) { - super(); - this.s = s; - } - - public String getChildElementXML() { - StringBuffer buf = new StringBuffer(); - buf.append(s); - return buf.toString(); - } - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleNegotiator.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleNegotiator.java deleted file mode 100644 index f7b1ce54e..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleNegotiator.java +++ /dev/null @@ -1,341 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import java.util.ArrayList; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleError; - -/** - * Basic Jingle negotiator. - * - * </p> - * - * JingleNegotiator implements some basic behavior for every Jingle negotiation. - * It implements a "state" pattern: each stage should process Jingle packets and - * act depending on the current state in the negotiation... - * - * </p> - * - * @author Alvaro Saurin - */ -public abstract class JingleNegotiator { - - private State state; // Current negotiation state - - private XMPPConnection connection; // The connection associated - - private final ArrayList listeners = new ArrayList(); - - private String expectedAckId; - - /** - * Default constructor. - */ - public JingleNegotiator() { - this(null); - } - - /** - * Default constructor with a XMPPConnection - * - * @param connection the connection associated - */ - public JingleNegotiator(final XMPPConnection connection) { - this.connection = connection; - state = null; - } - - /** - * Get the XMPP connection associated with this negotiation. - * - * @return the connection - */ - public XMPPConnection getConnection() { - return connection; - } - - /** - * Set the XMPP connection associated. - * - * @param connection the connection to set - */ - public void setConnection(final XMPPConnection connection) { - this.connection = connection; - } - - /** - * Inform if current state is null - * - * @return true if current state is null - */ - public boolean invalidState() { - return state == null; - } - - /** - * Return the current state - * - * @return the state - */ - public State getState() { - return state; - } - - /** - * Return the current state class - * - * @return the state - */ - public Class getStateClass() { - if (state != null) { - return state.getClass(); - } else { - return Object.class; - } - } - - /** - * Set the new state. - * - * @param state the state to set - * @throws XMPPException - */ - protected void setState(final State newState) { - boolean transition = newState != state; - - if (transition && state != null) { - state.eventExit(); - } - - state = newState; - - if (transition && state != null) { - state.eventEnter(); - } - } - - // Acks management - - public void addExpectedId(final String id) { - expectedAckId = id; - } - - public boolean isExpectedId(final String id) { - if (id != null) { - return id.equals(expectedAckId); - } else { - return false; - } - } - - public void removeExpectedId(final String id) { - addExpectedId((String) null); - } - - // Listeners - - /** - * Add a Jingle session listener to listen to incoming session requests. - * - * @param li The listener - * - * @see JingleListener - */ - public void addListener(final JingleListener li) { - synchronized (listeners) { - listeners.add(li); - } - } - - /** - * Removes a Jingle session listener. - * - * @param li The jingle session listener to be removed - * @see JingleListener - */ - public void removeListener(final JingleListener li) { - synchronized (listeners) { - listeners.remove(li); - } - } - - /** - * Get a copy of the listeners - * - * @return a copy of the listeners - */ - protected ArrayList getListenersList() { - ArrayList result; - - synchronized (listeners) { - result = new ArrayList(listeners); - } - - return result; - } - - /** - * Dispatch an incomming packet. This method is responsible for recognizing - * the packet type and, depending on the current state, deliverying the - * packet to the right event handler and wait for a response. - * - * @param iq the packet received - * @param id the ID of the response that will be sent - * @return the new packet to send (either a Jingle or an IQ error). - * @throws XMPPException - */ - public abstract IQ dispatchIncomingPacket(final IQ iq, final String id) - throws XMPPException; - - /** - * Close the negotiation. - */ - public void close() { - setState(null); - } - - /** - * A Jingle exception. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ - public static class JingleException extends XMPPException { - - private final JingleError error; - - /** - * Default constructor. - */ - public JingleException() { - super(); - error = null; - } - - /** - * Constructor with an error message. - * - * @param error The message. - */ - public JingleException(final String msg) { - super(msg); - error = null; - } - - /** - * Constructor with an error response. - * - * @param error The error message. - */ - public JingleException(final JingleError error) { - super(); - this.error = error; - } - - /** - * Return the error message. - * - * @return the error - */ - public JingleError getError() { - return error; - } - } - - /** - * Negotiation state and events. - * - * </p> - * - * Describes the negotiation stage. - */ - public static class State { - - private JingleNegotiator neg; // The negotiator - - /** - * Default constructor, with a reference to the negotiator. - * - * @param neg The negotiator instance. - */ - public State(final JingleNegotiator neg) { - this.neg = neg; - } - - /** - * Get the negotiator - * - * @return the negotiator. - */ - public JingleNegotiator getNegotiator() { - return neg; - } - - /** - * Set the negotiator. - * - * @param neg the neg to set - */ - public void setNegotiator(final JingleNegotiator neg) { - this.neg = neg; - } - - // State transition events - - public Jingle eventAck(final IQ iq) throws XMPPException { - // We have received an Ack - return null; - } - - public void eventError(final IQ iq) throws XMPPException { - throw new JingleException(iq.getError().getMessage()); - } - - public Jingle eventInvite() throws XMPPException { - throw new IllegalStateException( - "Negotiation can not be started in this state."); - } - - public Jingle eventInitiate(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventAccept(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventRedirect(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventModify(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventDecline(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventInfo(final Jingle jin) throws XMPPException { - return null; - } - - public Jingle eventTerminate(final Jingle jin) throws XMPPException { - if (neg != null) { - neg.close(); - } - return null; - } - - public void eventEnter() { - } - - public void eventExit() { - if (neg != null) { - neg.removeExpectedId(null); - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSession.java deleted file mode 100644 index 39d686fd3..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSession.java +++ /dev/null @@ -1,1020 +0,0 @@ -/** - * $RCSfile: JingleSession.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:12:42 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.jingle; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Random; -import org.jivesoftware.smack.ConnectionListener; -import org.jivesoftware.smack.PacketListener; -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.filter.PacketFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.packet.Packet; -import org.jivesoftware.smack.packet.XMPPError; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleContentInfo; -import org.jivesoftware.smackx.packet.JingleError; -import org.jivesoftware.smackx.packet.JingleTransport; -import org.jivesoftware.smackx.packet.JingleContentDescription.JinglePayloadType; -import org.jivesoftware.smackx.packet.JingleTransport.JingleTransportCandidate; - -/** - * A Jingle session. - * - * </p> - * - * This class contains some basic properties of every Jingle session. However, - * the concrete implementation will be found in subclasses. - * - * </p> - * - * @see IncomingJingleSession - * @see OutgoingJingleSession - * - * </p> - * @author Alvaro Saurin - */ -public abstract class JingleSession extends JingleNegotiator { - - // static - - private static final HashMap sessions = new HashMap(); - - private static final Random randomGenerator = new Random(); - - // non-static - - private String initiator; // Who started the communication - - private String responder; // The other endpoint - - private String sid; // A unique id that identifies this session - - private MediaNegotiator mediaNeg; // The description... - - private TransportNegotiator transNeg; // and transport negotiators - - PacketListener packetListener; - - PacketFilter packetFilter; - - /** - * Default constructor. - */ - public JingleSession(final XMPPConnection conn, final String ini, final String res, - final String sessionid) { - super(conn); - - mediaNeg = null; - transNeg = null; - - initiator = ini; - responder = res; - sid = sessionid; - - // Add the session to the list and register the listeneres - registerInstance(); - installConnectionListeners(conn); - } - - /** - * Default constructor without session id. - */ - public JingleSession(final XMPPConnection conn, final String ini, final String res) { - this(conn, ini, res, null); - } - - /** - * Get the session initiator - * - * @return the initiator - */ - public String getInitiator() { - return initiator; - } - - /** - * Set the session initiator - * - * @param initiator the initiator to set - */ - public void setInitiator(final String initiator) { - this.initiator = initiator; - } - - /** - * Get the session responder - * - * @return the responder - */ - public String getResponder() { - return responder; - } - - /** - * Set the session responder. - * - * @param responder the receptor to set - */ - public void setResponder(final String responder) { - this.responder = responder; - } - - /** - * Get the session ID - * - * @return the sid - */ - public String getSid() { - return sid; - } - - /** - * Set the session ID - * - * @param sid the sid to set - */ - protected void setSid(final String sessionId) { - sid = sessionId; - } - - /** - * Generate a unique session ID. - */ - protected String generateSessionId() { - StringBuffer buffer = new StringBuffer(); - buffer.append(Math.abs(randomGenerator.nextLong())); - - return buffer.toString(); - } - - /** - * Obtain the description negotiator for this session - * - * @return the description negotiator - */ - protected MediaNegotiator getMediaNeg() { - return mediaNeg; - } - - /** - * Set the media negotiator. - * - * @param mediaNeg the description negotiator to set - */ - protected void setMediaNeg(final MediaNegotiator mediaNeg) { - destroyMediaNeg(); - this.mediaNeg = mediaNeg; - } - - /** - * Destroy the media negotiator. - */ - protected void destroyMediaNeg() { - if (mediaNeg != null) { - mediaNeg.close(); - mediaNeg = null; - } - } - - /** - * Obtain the transport negotiator for this session. - * - * @return the transport negotiator instance - */ - protected TransportNegotiator getTransportNeg() { - return transNeg; - } - - /** - * @param transNeg the transNeg to set - */ - protected void setTransportNeg(final TransportNegotiator transNeg) { - destroyTransportNeg(); - this.transNeg = transNeg; - } - - /** - * Destroy the transport negotiator. - */ - protected void destroyTransportNeg() { - if (transNeg != null) { - transNeg.close(); - transNeg = null; - } - } - - /** - * Return true if the transport and content negotiators have finished - */ - public boolean isFullyEstablished() { - if (!isValid()) { - return false; - } - if (!getTransportNeg().isFullyEstablished() - || !getMediaNeg().isFullyEstablished()) { - return false; - } - return true; - } - - /** - * Return true if the session is valid (<i>ie</i>, it has all the required - * elements initialized). - * - * @return true if the session is valid. - */ - public boolean isValid() { - return mediaNeg != null && transNeg != null && sid != null && initiator != null; - } - - /** - * Dispatch an incoming packet. The medthod is responsible for recognizing - * the packet type and, depending on the current state, deliverying the - * packet to the right event handler and wait for a response. - * - * @param iq the packet received - * @return the new Jingle packet to send. - * @throws XMPPException - */ - public IQ dispatchIncomingPacket(final IQ iq, final String id) throws XMPPException { - IQ jout = null; - - if (invalidState()) { - throw new IllegalStateException( - "Illegal state in dispatch packet in Session manager."); - } else { - if (iq == null) { - // If there is no input packet, then we must be inviting... - jout = getState().eventInvite(); - } else { - if (iq.getType().equals(IQ.Type.ERROR)) { - // Process errors - getState().eventError(iq); - } else if (iq.getType().equals(IQ.Type.RESULT)) { - // Process ACKs - if (isExpectedId(iq.getPacketID())) { - jout = getState().eventAck(iq); - removeExpectedId(iq.getPacketID()); - } - } else if (iq instanceof Jingle) { - // It is not an error: it is a Jingle packet... - Jingle jin = (Jingle) iq; - Jingle.Action action = jin.getAction(); - - if (action != null) { - if (action.equals(Jingle.Action.SESSIONACCEPT)) { - jout = getState().eventAccept(jin); - } else if (action.equals(Jingle.Action.SESSIONINFO)) { - jout = getState().eventInfo(jin); - } else if (action.equals(Jingle.Action.SESSIONINITIATE)) { - jout = getState().eventInitiate(jin); - } else if (action.equals(Jingle.Action.SESSIONREDIRECT)) { - jout = getState().eventRedirect(jin); - } else if (action.equals(Jingle.Action.SESSIONTERMINATE)) { - jout = getState().eventTerminate(jin); - } - } else { - jout = errorMalformedStanza(iq); - } - } - } - - if (jout != null) { - // Save the packet id, for recognizing ACKs... - addExpectedId(jout.getPacketID()); - } - } - - return jout; - } - - /** - * Process and respond to an incomming packet. - * - * This method is called from the packet listener dispatcher when a new - * packet has arrived. The medthod is responsible for recognizing the packet - * type and, depending on the current state, deliverying it to the right - * event handler and wait for a response. The response will be another - * Jingle packet that will be sent to the other endpoint. - * - * @param iq the packet received - * @return the new Jingle packet to send. - * @throws XMPPException - */ - public synchronized IQ respond(final IQ iq) throws XMPPException { - IQ response = null; - - if (isValid()) { - String responseId = null; - IQ sessionResponse = null; - IQ descriptionResponse = null; - IQ transportResponse = null; - - // Send the packet to the right event handler for the session... - try { - sessionResponse = dispatchIncomingPacket(iq, null); - if (sessionResponse != null) { - responseId = sessionResponse.getPacketID(); - } - - // ... and do the same for the Description and Transport - // parts... - if (mediaNeg != null) { - descriptionResponse = mediaNeg.dispatchIncomingPacket(iq, responseId); - } - - if (transNeg != null) { - transportResponse = transNeg.dispatchIncomingPacket(iq, responseId); - } - - // Acknowledge the IQ reception - sendAck(iq); - - // ... and send all these parts in a Jingle response. - response = sendJingleParts(iq, (Jingle) sessionResponse, - (Jingle) descriptionResponse, (Jingle) transportResponse); - - } catch (JingleException e) { - // Send an error message, if present - JingleError error = e.getError(); - if (error != null) { - sendFormattedError(iq, error); - } - - // Notify the session end and close everything... - triggerSessionClosedOnError(e); - close(); - } - } - - return response; - } - - // Packet formatting and delivery - - /** - * Put together all the parts ina Jingle packet. - * - * @return the new Jingle packet - */ - private Jingle sendJingleParts(final IQ iq, final Jingle jSes, final Jingle jDesc, - final Jingle jTrans) { - Jingle response = null; - - if (jSes != null) { - jSes.addDescriptions(jDesc.getDescriptionsList()); - jSes.addTransports(jTrans.getTransportsList()); - - response = sendFormattedJingle(iq, jSes); - } else { - // If we don't have a valid session message, then we must send - // separated messages for transport and media... - if (jDesc != null) { - response = sendFormattedJingle(iq, jDesc); - } - - if (jTrans != null) { - response = sendFormattedJingle(iq, jTrans); - } - } - - return response; - } - - /** - * Complete and send an error. Complete all the null fields in an IQ error - * reponse, using the sesssion information we have or some info from the - * incoming packet. - * - * @param jin The Jingle packet we are responing to - * @param pout the IQ packet we want to complete and send - */ - protected IQ sendFormattedError(final IQ iq, final JingleError error) { - IQ perror = null; - if (error != null) { - perror = createIQ(getSid(), iq.getFrom(), iq.getTo(), IQ.Type.ERROR); - - // Fill in the fields with the info from the Jingle packet - perror.setPacketID(iq.getPacketID()); - perror.addExtension(error); - - getConnection().sendPacket(perror); - } - return perror; - } - - /** - * Complete and send a packet. Complete all the null fields in a Jingle - * reponse, using the session information we have or some info from the - * incoming packet. - * - * @param jin The Jingle packet we are responing to - * @param jout the Jingle packet we want to complete and send - */ - protected Jingle sendFormattedJingle(final IQ iq, final Jingle jout) { - if (jout != null) { - if (jout.getInitiator() == null) { - jout.setInitiator(getInitiator()); - } - - if (jout.getResponder() == null) { - jout.setResponder(getResponder()); - } - - if (jout.getSid() == null) { - jout.setSid(getSid()); - } - - String me = getConnection().getUser(); - String other = getResponder().equals(me) ? getInitiator() : getResponder(); - - if (jout.getTo() == null) { - if (iq != null) { - jout.setTo(iq.getFrom()); - } else { - jout.setTo(other); - } - } - - if (jout.getFrom() == null) { - if (iq != null) { - jout.setFrom(iq.getTo()); - } else { - jout.setFrom(me); - } - } - - getConnection().sendPacket(jout); - } - return jout; - } - - /** - * Complete and send a packet. Complete all the null fields in a Jingle - * reponse, using the session information we have. - * - * @param jout the Jingle packet we want to complete and send - */ - protected Jingle sendFormattedJingle(final Jingle jout) { - return sendFormattedJingle(null, jout); - } - - /** - * Send an error indicating that the stanza is malformed. - * - * @param iq - */ - protected IQ errorMalformedStanza(final IQ iq) { - // FIXME: implement with the right message... - return createError(iq.getPacketID(), iq.getFrom(), getConnection().getUser(), - 400, "Bad Request"); - } - - /** - * Check if we have an established session and, in that case, send an Accept - * packet. - */ - protected Jingle sendAcceptIfFullyEstablished() { - Jingle result = null; - if (isFullyEstablished()) { - // Ok, send a packet saying that we accept this session - Jingle jout = new Jingle(Jingle.Action.SESSIONACCEPT); - jout.setType(IQ.Type.SET); - - result = sendFormattedJingle(jout); - } - return result; - } - - /** - * Acknowledge a IQ packet. - * - * @param iq The IQ to acknowledge - */ - private IQ sendAck(final IQ iq) { - IQ result = null; - - if (iq != null) { - // Don't acknowledge ACKs, errors... - if (iq.getType().equals(IQ.Type.SET)) { - IQ ack = createIQ(iq.getPacketID(), iq.getFrom(), iq.getTo(), - IQ.Type.RESULT); - - getConnection().sendPacket(ack); - result = ack; - } - } - return result; - } - - /** - * Send a content info message. - */ - public synchronized void sendContentInfo(final ContentInfo ci) { - if (isValid()) { - sendFormattedJingle(new Jingle(new JingleContentInfo(ci))); - } - } - - /** - * Get the content description the other part has accepted. - * - * @param jin The Jingle packet where they have accepted the session. - * @return The audio PayloadType they have accepted. - * @throws XMPPException - */ - protected PayloadType.Audio getAcceptedAudioPayloadType(final Jingle jin) - throws XMPPException { - PayloadType.Audio acceptedPayloadType = null; - ArrayList jda = jin.getDescriptionsList(); - - if (jin.getAction().equals(Jingle.Action.SESSIONACCEPT)) { - - if (jda.size() > 1) { - throw new XMPPException( - "Unsupported feature: the number of accepted content descriptions is greater than 1."); - } else if (jda.size() == 1) { - JingleContentDescription jd = (JingleContentDescription) jda.get(0); - if (jd.getJinglePayloadTypesCount() > 1) { - throw new XMPPException( - "Unsupported feature: the number of accepted payload types is greater than 1."); - } - if (jd.getJinglePayloadTypesCount() == 1) { - JinglePayloadType jpt = (JinglePayloadType) jd - .getJinglePayloadTypesList().get(0); - acceptedPayloadType = (PayloadType.Audio) jpt.getPayloadType(); - } - } - } - return acceptedPayloadType; - } - - /** - * Get the accepted local candidate we have previously offered. - * - * @param jin The jingle packet where they accept the session - * @return The transport candidate they have accepted. - * @throws XMPPException - */ - protected TransportCandidate getAcceptedLocalCandidate(final Jingle jin) - throws XMPPException { - ArrayList jta = jin.getTransportsList(); - TransportCandidate acceptedLocalCandidate = null; - - if (jin.getAction().equals(Jingle.Action.SESSIONACCEPT)) { - if (jta.size() > 1) { - throw new XMPPException( - "Unsupported feature: the number of accepted transports is greater than 1."); - } else if (jta.size() == 1) { - JingleTransport jt = (JingleTransport) jta.get(0); - - if (jt.getCandidatesCount() > 1) { - throw new XMPPException( - "Unsupported feature: the number of accepted transport candidates is greater than 1."); - } else if (jt.getCandidatesCount() == 1) { - JingleTransportCandidate jtc = (JingleTransportCandidate) jt - .getCandidatesList().get(0); - acceptedLocalCandidate = jtc.getMediaTransport(); - } - } - } - - return acceptedLocalCandidate; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - return Jingle.getSessionHash(getSid(), getInitiator()); - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - - final JingleSession other = (JingleSession) obj; - - if (initiator == null) { - if (other.initiator != null) { - return false; - } - } else if (!initiator.equals(other.initiator)) { - return false; - } - - if (responder == null) { - if (other.responder != null) { - return false; - } - } else if (!responder.equals(other.responder)) { - return false; - } - - if (sid == null) { - if (other.sid != null) { - return false; - } - } else if (!sid.equals(other.sid)) { - return false; - } - - return true; - } - - // Instances management - - /** - * Clean a session from the list. - * - * @param connection The connection to clean up - */ - private void unregisterInstanceFor(final XMPPConnection connection) { - synchronized (sessions) { - sessions.remove(connection); - } - } - - /** - * Register this instance. - */ - private void registerInstance() { - synchronized (sessions) { - sessions.put(getConnection(), this); - } - } - - /** - * Returns the JingleSession related to a particular connection. - * - * @param con A XMPP connection - * @return a Jingle session - */ - public static JingleSession getInstanceFor(final XMPPConnection con) { - if (con == null) { - throw new IllegalArgumentException("Connection cannot be null"); - } - - JingleSession result = null; - synchronized (sessions) { - if (sessions.containsKey(con)) { - result = (JingleSession) sessions.get(con); - } - } - - return result; - } - - /** - * Configure a session, setting some action listeners... - * - * @param session The connection to set up - */ - private void installConnectionListeners(final XMPPConnection connection) { - if (connection != null) { - connection.addConnectionListener(new ConnectionListener() { - public void connectionClosed() { - unregisterInstanceFor(connection); - } - - public void connectionClosedOnError(final java.lang.Exception e) { - unregisterInstanceFor(connection); - } - }); - } - } - - /** - * Remove the packet listener used for processing packet. - */ - protected void removePacketListener() { - if (packetListener != null) { - getConnection().removePacketListener(packetListener); - } - } - - /** - * Install the packet listener. The listener is responsible for responding - * to any packet that we receive... - */ - protected void updatePacketListener() { - removePacketListener(); - - packetListener = new PacketListener() { - public void processPacket(final Packet packet) { - try { - respond((IQ) packet); - } catch (XMPPException e) { - e.printStackTrace(); - } - } - }; - - packetFilter = new PacketFilter() { - public boolean accept(final Packet packet) { - if (packet instanceof IQ) { - IQ iq = (IQ) packet; - - String me = getConnection().getUser(); - - if (!iq.getTo().equals(me)) { - return false; - } - - String other = getResponder().equals(me) ? getInitiator() - : getResponder(); - - if (!iq.getFrom().equals(other)) { - return false; - } - - if (iq instanceof Jingle) { - Jingle jin = (Jingle) iq; - - String sid = jin.getSid(); - if (!sid.equals(getSid())) { - return false; - } - String ini = jin.getInitiator(); - if (!ini.equals(getInitiator())) { - return false; - } - } else { - // We accept some non-Jingle IQ packets: ERRORs and ACKs - if (iq.getType().equals(IQ.Type.SET)) { - return false; - } else if (iq.getType().equals(IQ.Type.GET)) { - return false; - } - } - return true; - } - return false; - } - }; - - getConnection().addPacketListener(packetListener, packetFilter); - } - - // Listeners - - /** - * Add a listener for media negotiation events - * - * @param li The listener - */ - public void addMediaListener(final JingleListener.Media li) { - if (getMediaNeg() != null) { - getMediaNeg().addListener(li); - } - } - - /** - * Remove a listener for media negotiation events - * - * @param li The listener - */ - public void removeMediaListener(final JingleListener.Media li) { - if (getMediaNeg() != null) { - getMediaNeg().removeListener(li); - } - } - - /** - * Add a listener for transport negotiation events - * - * @param li The listener - */ - public void addTransportListener(final JingleListener.Transport li) { - if (getTransportNeg() != null) { - getTransportNeg().addListener(li); - } - } - - /** - * Remove a listener for transport negotiation events - * - * @param li The listener - */ - public void removeTransportListener(final JingleListener.Transport li) { - if (getTransportNeg() != null) { - getTransportNeg().removeListener(li); - } - } - - // Triggers - - /** - * Trigger a session closed event. - */ - protected void triggerSessionClosed(final String reason) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Session) { - JingleListener.Session sli = (JingleListener.Session) li; - sli.sessionClosed(reason); - } - } - } - - /** - * Trigger a session closed event due to an error. - */ - protected void triggerSessionClosedOnError(final XMPPException exc) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Session) { - JingleListener.Session sli = (JingleListener.Session) li; - sli.sessionClosedOnError(exc); - } - } - } - - /** - * Trigger a session established event. - */ - protected void triggerSessionEstablished(final PayloadType pt, - final TransportCandidate rc, final TransportCandidate lc) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Session) { - JingleListener.Session sli = (JingleListener.Session) li; - sli.sessionEstablished(pt, rc, lc); - } - } - } - - /** - * Trigger a session redirect event. - */ - protected void triggerSessionRedirect(final String arg) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Session) { - JingleListener.Session sli = (JingleListener.Session) li; - sli.sessionRedirected(arg); - } - } - } - - /** - * Trigger a session redirect event. - */ - protected void triggerSessionDeclined(final String reason) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Session) { - JingleListener.Session sli = (JingleListener.Session) li; - sli.sessionDeclined(reason); - } - } - } - - /** - * Start the negotiation. - * - * @throws JingleException - * @throws XMPPException - */ - public abstract void start(final JingleSessionRequest jin) throws XMPPException; - - /** - * Terminate negotiations. - */ - public void close() { - destroyMediaNeg(); - destroyTransportNeg(); - - removePacketListener(); - - super.close(); - } - - // Packet and error creation - - /** - * A convience method to create an IQ packet. - * - * @param ID The packet ID of the - * @param to To whom the packet is addressed. - * @param from From whom the packet is sent. - * @param type The iq type of the packet. - * @return The created IQ packet. - */ - public static IQ createIQ(final String ID, final String to, final String from, - final IQ.Type type) { - IQ iqPacket = new IQ() { - public String getChildElementXML() { - return null; - } - }; - - iqPacket.setPacketID(ID); - iqPacket.setTo(to); - iqPacket.setFrom(from); - iqPacket.setType(type); - - return iqPacket; - } - - /** - * A convience method to create an error packet. - * - * @param ID The packet ID of the - * @param to To whom the packet is addressed. - * @param from From whom the packet is sent. - * @param errCode The error code. - * @param errStr The error string. - * - * @return The created IQ packet. - */ - public static IQ createError(final String ID, final String to, final String from, - final int errCode, final String errStr) { - - IQ iqError = createIQ(ID, to, from, IQ.Type.ERROR); - XMPPError error = new XMPPError(errCode, errStr); - iqError.setError(error); - - return iqError; - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionRequest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionRequest.java deleted file mode 100644 index 53edbf667..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionRequest.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import java.util.List; - -import org.jivesoftware.smackx.packet.Jingle; - -/** - * A Jingle session request. - * - * </p> - * - * This class is a facade of a received Jingle request. The user can have direct - * access to the Jingle packet (<i>JingleSessionRequest.getJingle() </i>) of - * the request or can use the convencience methods provided by this class. - * - * </p> - * - * @author Alvaro Saurin - */ -public class JingleSessionRequest { - - private final Jingle jingle; // The Jingle packet - - private final JingleManager manager; // The manager associated to this - - // request - - /** - * A recieve request is constructed from the Jingle Initiation request - * received from the initator. - * - * @param manager The manager handling this request - * @param jingle The jingle IQ recieved from the initiator. - */ - public JingleSessionRequest(final JingleManager manager, final Jingle jingle) { - this.manager = manager; - this.jingle = jingle; - } - - /** - * Returns the fully-qualified jabber ID of the user that requested this - * session. - * - * @return Returns the fully-qualified jabber ID of the user that requested - * this session. - */ - public String getFrom() { - return jingle.getFrom(); - } - - /** - * Returns the session ID that uniquely identifies this session. - * - * @return Returns the session ID that uniquely identifies this session - */ - public String getSessionID() { - return jingle.getSid(); - } - - /** - * Returns the Jingle packet that was sent by the requestor which contains - * the parameters of the session. - */ - protected Jingle getJingle() { - return jingle; - } - - /** - * Accepts this request and creates the incoming Jingle session. - * - * @return Returns the <b><i>IncomingJingleSession</b></i> on which the - * negotiation can be carried out. - */ - public synchronized IncomingJingleSession accept(final List pts) { - IncomingJingleSession session = null; - synchronized (manager) { - session = manager.createIncomingJingleSession(this, - pts); - } - return session; - } - - /** - * Rejects the session request. - */ - public synchronized void reject() { - synchronized (manager) { - manager.rejectIncomingJingleSession(this); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionTest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionTest.java deleted file mode 100644 index 6ce8add71..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/JingleSessionTest.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import org.jivesoftware.smack.test.SmackTestCase; - -public class JingleSessionTest extends SmackTestCase { - - public JingleSessionTest(final String name) { - super(name); - } - - public void testEqualsObject() { - JingleSession js1 = new OutgoingJingleSession(getConnection(0), "res1", null, null); - JingleSession js2 = new OutgoingJingleSession(getConnection(1), "res1", null, null); - JingleSession js3 = new OutgoingJingleSession(getConnection(2), "res2", null, null); - - assertEquals(js1, js2); - assertEquals(js2, js1); - - assertFalse(js1.equals(js3)); - } - - public void testGetInstanceFor() { - String ini1 = "initiator1"; - String sid1 = "sid1"; - String ini2 = "initiator2"; - String sid2 = "sid2"; - - JingleSession js1 = new OutgoingJingleSession(getConnection(0), sid1, null, null); - JingleSession js2 = new OutgoingJingleSession(getConnection(1), sid2, null, null); - - // For a packet, we should be able to get a session that handles that... - assertNotNull(JingleSession.getInstanceFor(getConnection(0))); - assertNotNull(JingleSession.getInstanceFor(getConnection(1))); - - assertEquals(JingleSession.getInstanceFor(getConnection(0)), js1); - assertEquals(JingleSession.getInstanceFor(getConnection(1)), js2); - } - - protected int getMaxConnections() { - return 3; - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/MediaNegotiator.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/MediaNegotiator.java deleted file mode 100644 index 5cd2354b8..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/MediaNegotiator.java +++ /dev/null @@ -1,553 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleError; -import org.jivesoftware.smackx.packet.JingleContentDescription.JinglePayloadType; - -/** - * Manager for media descriptor negotiation. - * - * </p> - * - * This class is responsible for managing the descriptor negotiation process, - * handling all the packet interchange and the stage control. - * - * </p> - * - * @author Alvaro Saurin - */ -public class MediaNegotiator extends JingleNegotiator { - - private final JingleSession session; // The session this negotiation - - // Local and remote payload types... - - private final List localAudioPts = new ArrayList(); - - private final List remoteAudioPts = new ArrayList(); - - private PayloadType.Audio bestCommonAudioPt; - - // states - - private final Inviting inviting; - - private final Accepting accepting; - - private final Pending pending; - - private final Active active; - - /** - * Default constructor. The constructor establishes some basic parameters, - * but it does not start the negotiation. For starting the negotiation, call - * startNegotiation. - * - * @param js The jingle session. - */ - public MediaNegotiator(final JingleSession js, final List pts) { - super(js.getConnection()); - - session = js; - - bestCommonAudioPt = null; - - if (pts != null) { - if (pts.size() > 0) { - localAudioPts.addAll(pts); - } - } - - // Create the states... - inviting = new Inviting(this); - accepting = new Accepting(this); - pending = new Pending(this); - active = new Active(this); - } - - /** - * Dispatch an incomming packet. The medthod is responsible for recognizing - * the packet type and, depending on the current state, deliverying the - * packet to the right event handler and wait for a response. - * - * @param iq the packet received - * @return the new Jingle packet to send. - * @throws XMPPException - */ - public IQ dispatchIncomingPacket(final IQ iq, final String id) throws XMPPException { - IQ jout = null; - - if (invalidState()) { - if (iq == null) { - // With a null packet, we are just inviting the other end... - setState(inviting); - jout = getState().eventInvite(); - } else { - if (iq instanceof Jingle) { - // If there is no specific media action associated, then we - // are being invited to a new session... - setState(accepting); - jout = getState().eventInitiate((Jingle) iq); - } else { - throw new IllegalStateException( - "Invitation IQ received is not a Jingle packet in Media negotiator."); - } - } - } else { - if (iq == null) { - return null; - } else { - if (iq.getType().equals(IQ.Type.ERROR)) { - // Process errors - getState().eventError(iq); - } else if (iq.getType().equals(IQ.Type.RESULT)) { - // Process ACKs - if (isExpectedId(iq.getPacketID())) { - jout = getState().eventAck(iq); - removeExpectedId(iq.getPacketID()); - } - } else if (iq instanceof Jingle) { - // Get the action from the Jingle packet - Jingle jin = (Jingle) iq; - Jingle.Action action = jin.getAction(); - - if (action != null) { - if (action.equals(Jingle.Action.CONTENTACCEPT)) { - jout = getState().eventAccept(jin); - } else if (action.equals(Jingle.Action.CONTENTDECLINE)) { - jout = getState().eventDecline(jin); - } else if (action.equals(Jingle.Action.CONTENTINFO)) { - jout = getState().eventInfo(jin); - } else if (action.equals(Jingle.Action.CONTENTMODIFY)) { - jout = getState().eventModify(jin); - } - // Any unknown action will be ignored: it is not a msg - // to us... - } - } - } - } - - // Save the Id for any ACK - if (id != null) { - addExpectedId(id); - } else { - if (jout != null) { - addExpectedId(jout.getPacketID()); - } - } - - return jout; - } - - /** - * Return true if the content is negotiated. - * - * @return true if the content is negotiated. - */ - public boolean isEstablished() { - return getBestCommonAudioPt() != null; - } - - /** - * Return true if the content is fully negotiated. - * - * @return true if the content is fully negotiated. - */ - public boolean isFullyEstablished() { - return isEstablished() && getState() == active; - } - - // Payload types - - private PayloadType.Audio calculateBestCommonAudioPt(final List remoteAudioPts) { - final ArrayList commonAudioPtsHere = new ArrayList(); - final ArrayList commonAudioPtsThere = new ArrayList(); - PayloadType.Audio result = null; - - if (!remoteAudioPts.isEmpty()) { - commonAudioPtsHere.addAll(localAudioPts); - commonAudioPtsHere.retainAll(remoteAudioPts); - - commonAudioPtsThere.addAll(remoteAudioPts); - commonAudioPtsThere.retainAll(localAudioPts); - - 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 - 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)) { - result = bestPtHere; - } else { - result = bestPtThere; - } - } - } - } - - return result; - } - - private List obtainPayloads(final Jingle jin) { - List result = new ArrayList(); - Iterator iDescr = jin.getDescriptions(); - - // Add the list of payloads: iterate over the descriptions... - while (iDescr.hasNext()) { - JingleContentDescription.Audio descr = (JingleContentDescription.Audio) iDescr - .next(); - - if (descr != null) { - // ...and, then, over the payloads. - // Note: we use the last "description" in the packet... - result.clear(); - result.addAll(descr.getAudioPayloadTypesList()); - } - } - - return result; - } - - /** - * Adds a payload type to the list of remote payloads. - * - * @param pt the remote payload type - */ - public void addRemoteAudioPayloadType(final PayloadType.Audio pt) { - if (pt != null) { - synchronized (remoteAudioPts) { - remoteAudioPts.add(pt); - } - } - } - - /** - * Create an offer for the list of audio payload types. - * - * @return a new Jingle packet with the list of audio Payload Types - */ - private Jingle getAudioPayloadTypesOffer() { - JingleContentDescription.Audio audioDescr = new JingleContentDescription.Audio(); - - // Add the list of payloads for audio and create a - // JingleContentDescription - // where we announce our payloads... - audioDescr.addAudioPayloadTypes(localAudioPts); - - return new Jingle(audioDescr); - } - - // Predefined messages and Errors - - /** - * Create an IQ "accept" message. - */ - private Jingle createAcceptMessage() { - Jingle jout = null; - - // If we hava a common best codec, send an accept right now... - jout = new Jingle(Jingle.Action.CONTENTACCEPT); - jout.addDescription(new JingleContentDescription.Audio( - new JinglePayloadType.Audio(bestCommonAudioPt))); - - return jout; - } - - // Payloads - - /** - * Get the best common codec between both parts. - * - * @return The best common PayloadType codec. - */ - public PayloadType.Audio getBestCommonAudioPt() { - return bestCommonAudioPt; - } - - // Events - - /** - * Trigger a session established event. - * - * @param best payload type that has been agreed. - */ - protected void triggerMediaEstablished(final PayloadType bestPt) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Media) { - JingleListener.Media mli = (JingleListener.Media) li; - mli.mediaEstablished(bestPt); - } - } - } - - /** - * Trigger a media closed event. - * - * @param currPt current payload type that is cancelled. - */ - protected void triggerMediaClosed(final PayloadType currPt) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Media) { - JingleListener.Media mli = (JingleListener.Media) li; - mli.mediaClosed(currPt); - } - } - } - - /** - * Terminate the media negotiator - */ - public void close() { - super.close(); - } - - // States - - /** - * First stage when we send a session request. - */ - public class Inviting extends JingleNegotiator.State { - public Inviting(final MediaNegotiator neg) { - super(neg); - } - - /** - * Create an initial Jingle packet, with the list of payload types that - * we support. The list is in order of preference. - */ - public Jingle eventInvite() { - return getAudioPayloadTypesOffer(); - } - - /** - * We have received the ACK for our invitation. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) { - setState(pending); - return null; - } - } - - /** - * We are accepting connections. - */ - public class Accepting extends JingleNegotiator.State { - - public Accepting(final MediaNegotiator neg) { - super(neg); - } - - /** - * We have received an invitation! Respond with a list of our payload - * types... - */ - public Jingle eventInitiate(final Jingle jin) { - synchronized (remoteAudioPts) { - remoteAudioPts.addAll(obtainPayloads(jin)); - } - - return getAudioPayloadTypesOffer(); - } - - /** - * Process the ACK of our list of codecs (our offer). - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) throws XMPPException { - Jingle response = null; - - if (!remoteAudioPts.isEmpty()) { - // Calculate the best common codec - bestCommonAudioPt = calculateBestCommonAudioPt(remoteAudioPts); - - // and send an accept if we havee an agreement... - if (bestCommonAudioPt != null) { - response = createAcceptMessage(); - } else { - throw new JingleException(JingleError.NO_COMMON_PAYLOAD); - } - - setState(pending); - } - - return response; - } - } - - /** - * Pending class: we are waiting for the other enpoint, that must say if it - * accepts or not... - */ - public class Pending extends JingleNegotiator.State { - public Pending(final MediaNegotiator neg) { - super(neg); - } - - /** - * A content info has been received. This is done for publishing the - * list of payload types... - * - * @param jin The input packet - * @return a Jingle packet - * @throws JingleException - */ - public Jingle eventInfo(final Jingle jin) throws JingleException { - PayloadType.Audio oldBestCommonAudioPt = bestCommonAudioPt; - List offeredPayloads = new ArrayList(); - Jingle response = null; - boolean ptChange = false; - - offeredPayloads = obtainPayloads(jin); - if (!offeredPayloads.isEmpty()) { - - synchronized (remoteAudioPts) { - remoteAudioPts.clear(); - remoteAudioPts.addAll(offeredPayloads); - } - - // Calculate the best common codec - bestCommonAudioPt = calculateBestCommonAudioPt(remoteAudioPts); - if (bestCommonAudioPt != null) { - // and send an accept if we have an agreement... - ptChange = !bestCommonAudioPt.equals(oldBestCommonAudioPt); - if (oldBestCommonAudioPt == null || ptChange) { - response = createAcceptMessage(); - } - } else { - throw new JingleException(JingleError.NO_COMMON_PAYLOAD); - } - } - - // Parse the Jingle and get the payload accepted - return response; - } - - /** - * A media description has been accepted. In this case, we must save the - * accepted payload type and notify any listener... - * - * @param jin The input packet - * @return a Jingle packet - * @throws JingleException - */ - public Jingle eventAccept(final Jingle jin) throws JingleException { - PayloadType.Audio agreedCommonAudioPt; - List offeredPayloads = new ArrayList(); - Jingle response = null; - - if (bestCommonAudioPt == null) { - // Update the best common audio PT - bestCommonAudioPt = calculateBestCommonAudioPt(remoteAudioPts); - response = createAcceptMessage(); - } - - offeredPayloads = obtainPayloads(jin); - if (!offeredPayloads.isEmpty()) { - if (offeredPayloads.size() == 1) { - agreedCommonAudioPt = (PayloadType.Audio) offeredPayloads.get(0); - if (bestCommonAudioPt != null) { - // If the accepted PT matches the best payload - // everything is fine - if (!agreedCommonAudioPt.equals(bestCommonAudioPt)) { - throw new JingleException(JingleError.NEGOTIATION_ERROR); - } - } - - } else if (offeredPayloads.size() > 1) { - throw new JingleException(JingleError.MALFORMED_STANZA); - } - } - - return response; - } - - /** - * The other part has declined the our codec... - * - * @throws JingleException - */ - public Jingle eventDecline(final Jingle inJingle) throws JingleException { - triggerMediaClosed(getBestCommonAudioPt()); - throw new JingleException(); - } - - /* - * (non-Javadoc) - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventError(org.jivesoftware.smack.packet.IQ) - */ - public void eventError(final IQ iq) throws XMPPException { - triggerMediaClosed(getBestCommonAudioPt()); - super.eventError(iq); - } - - /** - * ACK received. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) { - if (isEstablished()) { - setState(active); - } - - return null; - } - } - - /** - * "Active" state: we have an agreement about the codec... - */ - public class Active extends JingleNegotiator.State { - - public Active(final MediaNegotiator neg) { - super(neg); - } - - /** - * We have an agreement. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - triggerMediaEstablished(getBestCommonAudioPt()); - super.eventEnter(); - } - - /** - * We are breaking the contract... - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventExit() - */ - public void eventExit() { - triggerMediaClosed(getBestCommonAudioPt()); - super.eventExit(); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/OutgoingJingleSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/OutgoingJingleSession.java deleted file mode 100644 index 2589f1d7b..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/OutgoingJingleSession.java +++ /dev/null @@ -1,405 +0,0 @@ -/** - * $RCSfile: OutgoingJingleSession.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:12:42 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.jingle; - -import java.util.List; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleError; -import org.jivesoftware.smackx.packet.JingleContentDescription.JinglePayloadType; - -/** - * An outgoing Jingle session. - * - * </p> - * - * This class is not directly used by users. Instead, users should refer to the - * JingleManager class, that will create the appropiate instance... - * - * </p> - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public class OutgoingJingleSession extends JingleSession { - - // states - - private final Inviting inviting; - - private final Pending pending; - - private final Active active; - - /** - * Constructor for a Jingle outgoing session. - * - * @param conn the XMPP connection - * @param responder the other endpoint - * @param payloadTypes A list of payload types, in order of preference. - * @param resolver The transport resolver. - */ - public OutgoingJingleSession(final XMPPConnection conn, final String responder, - final List payloadTypes, final TransportResolver resolver) { - - super(conn, conn.getUser(), responder); - - setSid(generateSessionId()); - - // Initialize the states. - inviting = new Inviting(this); - pending = new Pending(this); - active = new Active(this); - - // Create description and transport negotiatiors... - setMediaNeg(new MediaNegotiator(this, payloadTypes)); - setTransportNeg(new TransportNegotiator.RawUdp(this, resolver)); - } - - /** - * Initiate the negotiation with an invitation. This method must be invoked - * for starting all negotiations. It is the initial starting point and, - * afterwards, any other packet processing is done with the packet listener - * callback... - * - * @throws IllegalStateException - */ - public void start(final JingleSessionRequest req) throws IllegalStateException { - if (invalidState()) { - setState(inviting); - - // Use the standard behavior, using a null Jingle packet - try { - updatePacketListener(); - respond((Jingle) null); - } catch (XMPPException e) { - e.printStackTrace(); - close(); - } - } else { - throw new IllegalStateException("Starting session without null state."); - } - } - - // States - - /** - * Current state when we want to invite the other endpoint. - */ - public class Inviting extends JingleNegotiator.State { - - public Inviting(final JingleNegotiator neg) { - super(neg); - } - - /** - * Create an invitation packet. - */ - public Jingle eventInvite() { - // Create an invitation packet, saving the Packet ID, for any ACK - return new Jingle(Jingle.Action.SESSIONINITIATE); - } - - /** - * The receiver has partially accepted our invitation. We go to the - * pending state while the content and transport negotiators work... - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) { - setState(pending); - return null; - } - - /** - * The other endpoint has declined the invitation with an error. - * - * @throws XMPPException - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventError(org.jivesoftware.smack.packet.IQ) - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionDeclined(null); - super.eventError(iq); - } - - /** - * The other endpoint wants to redirect this connection. - */ - public Jingle eventRedirect(final Jingle jin) { - String redirArg = null; - - // TODO: parse the redirection parameters... - - triggerSessionRedirect(redirArg); - return null; - } - } - - /** - * "Pending" state: we are waiting for the transport and content - * negotiators. - * - * Note: the transition from/to this state is done with listeners... - */ - public class Pending extends JingleNegotiator.State { - JingleListener.Media mediaListener; - - JingleListener.Transport transportListener; - - public Pending(final JingleNegotiator neg) { - super(neg); - - // Create the listeners that will send a "session-accept" when - // the sub-negotiators are done. - mediaListener = new JingleListener.Media() { - public void mediaClosed(final PayloadType cand) { - } - - public void mediaEstablished(final PayloadType pt) { - checkFullyEstablished(); - } - }; - - transportListener = new JingleListener.Transport() { - public void transportEstablished(final TransportCandidate local, - final TransportCandidate remote) { - checkFullyEstablished(); - } - - public void transportClosed(final TransportCandidate cand) { - } - - public void transportClosedOnError(final XMPPException e) { - } - }; - } - - /** - * Enter in the pending state: install the listeners. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - // Add the listeners to the sub-negotiators... - addMediaListener(mediaListener); - addTransportListener(transportListener); - } - - /** - * Exit of the state: remove the listeners. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventExit() - */ - public void eventExit() { - removeMediaListener(mediaListener); - removeTransportListener(transportListener); - } - - /** - * Check if the session has been fully accepted by all the - * sub-negotiators and, in that case, send an "accept" message... - */ - private void checkFullyEstablished() { - - if (isFullyEstablished()) { - - PayloadType.Audio bestCommonAudioPt = getMediaNeg() - .getBestCommonAudioPt(); - TransportCandidate bestRemoteCandidate = getTransportNeg() - .getBestRemoteCandidate(); - - // Ok, send a packet saying that we accept this session - // with the audio payload type and the transport - // candidate - Jingle jout = new Jingle(Jingle.Action.SESSIONACCEPT); - jout.addDescription(new JingleContentDescription.Audio( - new JinglePayloadType(bestCommonAudioPt))); - jout.addTransport(getTransportNeg().getJingleTransport( - bestRemoteCandidate)); - - // Send the "accept" and wait for the ACK - addExpectedId(jout.getPacketID()); - sendFormattedJingle(jout); - } - } - - /** - * The other endpoint has finally accepted our invitation. - * - * @throws XMPPException - */ - public Jingle eventAccept(final Jingle jin) throws XMPPException { - - PayloadType acceptedPayloadType = null; - TransportCandidate acceptedLocalCandidate = null; - - // We process the "accepted" if we have finished the - // sub-negotiators. Maybe this is not needed (ie, the other endpoint - // can take the first valid transport candidate), but otherwise we - // must cancel the negotiators... - // - if (isFullyEstablished()) { - acceptedPayloadType = getAcceptedAudioPayloadType(jin); - acceptedLocalCandidate = getAcceptedLocalCandidate(jin); - - if (acceptedPayloadType != null && acceptedLocalCandidate != null) { - if (acceptedPayloadType.equals(getMediaNeg().getBestCommonAudioPt()) - && acceptedLocalCandidate.equals(getTransportNeg() - .getAcceptedLocalCandidate())) { - setState(active); - } - } else { - throw new JingleException(JingleError.NEGOTIATION_ERROR); - } - } - - return null; - } - - /** - * We have received the Ack of our "accept" - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAck(org.jivesoftware.smack.packet.IQ) - */ - public Jingle eventAck(final IQ iq) { - setState(active); - return null; - } - - /** - * The other endpoint wants to redirect this connection. - */ - public Jingle eventRedirect(final Jingle jin) { - String redirArg = null; - - // TODO: parse the redirection parameters... - - triggerSessionRedirect(redirArg); - return null; - } - - /** - * The other endpoint has rejected our invitation. - * - * @throws XMPPException - */ - public Jingle eventTerminate(final Jingle jin) throws XMPPException { - triggerSessionDeclined(null); - return super.eventTerminate(jin); - } - - /** - * An error has occurred. - * - * @throws XMPPException - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionClosedOnError(new XMPPException(iq.getError().getMessage())); - super.eventError(iq); - } - } - - /** - * State when we have an established session. - */ - public class Active extends JingleNegotiator.State { - public Active(final JingleNegotiator neg) { - super(neg); - } - - /** - * We have a established session: notify the listeners - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - PayloadType.Audio bestCommonAudioPt = getMediaNeg().getBestCommonAudioPt(); - TransportCandidate bestRemoteCandidate = getTransportNeg() - .getBestRemoteCandidate(); - TransportCandidate acceptedLocalCandidate = getTransportNeg() - .getAcceptedLocalCandidate(); - - // Trigger the session established flag - triggerSessionEstablished(bestCommonAudioPt, bestRemoteCandidate, - acceptedLocalCandidate); - - super.eventEnter(); - } - - /** - * Terminate the connection. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventTerminate(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventTerminate(final Jingle jin) throws XMPPException { - triggerSessionClosed(null); - return super.eventTerminate(jin); - } - - /** - * An error has occurred. - * - * @throws XMPPException - */ - public void eventError(final IQ iq) throws XMPPException { - triggerSessionClosedOnError(new XMPPException(iq.getError().getMessage())); - super.eventError(iq); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/PayloadType.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/PayloadType.java deleted file mode 100644 index e1a97f1a7..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/PayloadType.java +++ /dev/null @@ -1,289 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -/** - * Represents a payload type. - * - * @author Alvaro Saurin - */ -public class PayloadType { - - public static int MAX_FIXED_PT = 95; - - public static int INVALID_PT = 65535; - - private int id; - - private String name; - - private int channels; - - /** - * Constructor with Id, name and number of channels - * - * @param id The identifier - * @param name A name - * @param channels The number of channels - */ - public PayloadType(final int id, final String name, final int channels) { - super(); - this.id = id; - this.name = name; - this.channels = channels; - } - - /** - * Default constructor. - */ - public PayloadType() { - this(INVALID_PT, null, 1); - } - - /** - * Constructor with Id and name - * - * @param id The identification - * @param name A name - */ - public PayloadType(final int id, final String name) { - this(id, name, 1); - } - - /** - * Copy constructor - * - * @param pt The other payload type. - */ - public PayloadType(final PayloadType pt) { - this(pt.getId(), pt.getName(), pt.getChannels()); - } - - /** - * Get the ID. - * - * @return the ID - */ - public int getId() { - return id; - } - - /** - * Set the ID. - * - * @param id ID - */ - public void setId(final int id) { - this.id = id; - } - - /** - * Get the printable name. - * - * @return printable name for the payload type - */ - public String getName() { - return name; - } - - /** - * Set the printable name. - * - * @param name the printable name - */ - public void setName(final String name) { - this.name = name; - } - - /** - * Get the number of channels used by this payload type. - * - * @return the number of channels - */ - public int getChannels() { - return channels; - } - - /** - * Set the numer of channels for a payload type. - * - * @param channels The number of channels - */ - public void setChannels(final int channels) { - this.channels = channels; - } - - /** - * Return true if the Payload type is not valid - * - * @return true if the payload type is invalid - */ - public boolean isNull() { - if (getId() == INVALID_PT) { - return true; - } else if (getName() == null) { - return true; - } - return false; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - final int PRIME = 31; - int result = 1; - result = PRIME * result + getChannels(); - result = PRIME * result + getId(); - result = PRIME * result + (getName() == null ? 0 : getName().hashCode()); - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final PayloadType other = (PayloadType) obj; - if (getChannels() != other.getChannels()) { - return false; - } - if (getId() != other.getId()) { - return false; - } - - // Compare names only for dynamic payload types - if (getId() > MAX_FIXED_PT) { - if (getName() == null) { - if (other.getName() != null) { - return false; - } - } else if (!getName().equals(other.getName())) { - return false; - } - } - - return true; - } - - /** - * Audio payload type. - */ - public static class Audio extends PayloadType { - private int clockRate; - - /** - * Constructor with all the attributes of an Audio payload type - * - * @param id The identifier - * @param name The name assigned to this payload type - * @param channels The number of channels - * @param rate The clock rate - */ - public Audio(final int id, final String name, final int channels, final int rate) { - super(id, name, channels); - clockRate = rate; - } - - /** - * Empty constructor. - */ - public Audio() { - super(); - clockRate = 0; - } - - /** - * Constructor with Id and name - * - * @param id the Id for the payload type - * @param name the name of the payload type - */ - public Audio(final int id, final String name) { - super(id, name); - clockRate = 0; - } - - /** - * Copy constructor - * - * @param pt the other payload type - */ - public Audio(final PayloadType pt) { - super(pt); - clockRate = 0; - } - - /** - * Copy constructor - * - * @param pt the other payload type - */ - public Audio(final PayloadType.Audio pt) { - super(pt); - clockRate = pt.getClockRate(); - } - - /** - * Get the sampling clockRate for a payload type - * - * @return The sampling clockRate - */ - public int getClockRate() { - return clockRate; - } - - /** - * Set tha sampling clockRate for a playload type. - * - * @param rate The sampling clockRate - */ - public void setClockRate(final int rate) { - clockRate = rate; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - final int PRIME = 31; - int result = super.hashCode(); - result = PRIME * result + getClockRate(); - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Audio other = (Audio) obj; - if (getClockRate() != other.getClockRate()) { - return false; - } - return true; - } - } -}
\ No newline at end of file diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportManager.java deleted file mode 100644 index 54acebab9..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportManager.java +++ /dev/null @@ -1,171 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.nat.BasicResolver; -import org.jivesoftware.smackx.nat.FixedResolver; -import org.jivesoftware.smackx.nat.STUNResolver; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.packet.JingleTransport; - -/** - * Transport manager for Jingle. - * - * This class makes easier the use of transport resolvers by presenting a simple - * interface for algorithm selection. The transport manager also keeps the match - * between the resolution method and the <transport> element present in - * Jingle packets. - * - * This class must be used with a JingleManager instance in the following way: - * - * <pre> - * TransportManager tm = new TransportManager(); - * tm.useSTUN(); // or some other method... - * - * JingleManager jm = new JingleManager(connection, tm.getResolver()); - * jm.createOutgoingJingleSession(responder, payloads); - * </pre> - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public class TransportManager { - // This class implements the context of a Strategy pattern... - - // Current resolver. - private TransportResolver resolver; - - // An instance of the transport resolver. This doesn't need to match - // the resolver, as we can use a STUNResolver for the JingleTransport.Ice or - // JingleTransport.RawUdp resolvers... - private JingleTransport jingleTransport; - - /** - * Deafult contructor. - */ - public TransportManager() { - useSTUNResolver(); // We use Raw-UDP/STUN by default... - } - - /** - * Contructor with an external resolver. - */ - public TransportManager(final TransportResolver resol, final JingleTransport trans) { - resolver = resol; - jingleTransport = trans; - } - - /** - * Use the simple resolver. - */ - public void useSimpleResolver() { - if (resolver != null && !(resolver instanceof BasicResolver)) { - try { - resolver.cancel(); - } catch (XMPPException e) { - e.printStackTrace(); - } - } - resolver = new BasicResolver(); - - if (jingleTransport == null - || !(jingleTransport instanceof JingleTransport.RawUdp)) { - jingleTransport = new JingleTransport.RawUdp(); - } - } - - /** - * Use a simple resolver, with a fixed IP address and port. - * - * @param ip the IP address - * @param port the port to use (0 for any port) - */ - public void useSimpleResolver(final String ip, final int port) { - if (resolver != null && !(resolver instanceof FixedResolver)) { - try { - resolver.cancel(); - } catch (XMPPException e) { - e.printStackTrace(); - } - } - resolver = new FixedResolver(ip, port); - - if (jingleTransport == null - || !(jingleTransport instanceof JingleTransport.RawUdp)) { - jingleTransport = new JingleTransport.RawUdp(); - } - } - - /** - * Returns true if the transport manager is using the simple resolver - * - * @return true if the transport manager is using the simple resolver - */ - public boolean isUsingSimpleResolver() { - return (resolver instanceof BasicResolver || resolver instanceof FixedResolver) - && jingleTransport instanceof JingleTransport.RawUdp; - } - - /** - * Use the STUN resolver. - */ - public void useSTUNResolver() { - if (resolver != null && !(resolver instanceof STUNResolver)) { - try { - resolver.cancel(); - } catch (XMPPException e) { - e.printStackTrace(); - } - } - resolver = new STUNResolver(); - - if (jingleTransport == null - || !(jingleTransport instanceof JingleTransport.RawUdp)) { - jingleTransport = new JingleTransport.RawUdp(); - } - } - - /** - * Returns true if the transport manager is using the STUN resolver - * - * @return true if the transport manager is using the STUN resolver - */ - public boolean isUsingSTUNResolver() { - return resolver instanceof STUNResolver - && jingleTransport instanceof JingleTransport.RawUdp; - } - - /** - * Use the ICE resolver. - */ - public void useICEResolver() { - // Not implemented yet - resolver = null; - jingleTransport = new JingleTransport.Ice(); - } - - /** - * Returns true if the transport manager is using the ICE resolver - * - * @return true if the transport manager is using the ICE resolver - */ - public boolean isUsingICEResolver() { - return false; - } - - /** - * Obtain the JingleTransport for the current resolver - * - * @return a JingleTransport instance - */ - public JingleTransport getJingleTransport() { - return jingleTransport; - } - - /** - * Obtain the resolver - * - * @return a TransportResolver. - */ - public TransportResolver getResolver() { - return resolver; - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportNegotiator.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportNegotiator.java deleted file mode 100644 index bddb84b5b..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/TransportNegotiator.java +++ /dev/null @@ -1,797 +0,0 @@ -package org.jivesoftware.smackx.jingle; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.nat.TransportResolverListener; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleTransport; -import org.jivesoftware.smackx.packet.JingleTransport.JingleTransportCandidate; - -/** - * Transport negotiator. - * - * </p> - * - * This class is responsible for managing the transport negotiation process, - * handling all the packet interchange and the stage control. - * - * </p> - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class TransportNegotiator extends JingleNegotiator { - - // The time we give to the candidates check before we accept or decline the - // transport (in milliseconds) - public final static int CANDIDATES_ACCEPT_PERIOD = 4000; - - // The session this nenotiator belongs to - private JingleSession session; - - // The transport manager - private final TransportResolver resolver; - - // Transport candidates we have offered - private final List offeredCandidates = new ArrayList(); - - // List of remote transport candidates - private final List remoteCandidates = new ArrayList(); - - // Valid remote candidates - private final List validRemoteCandidates = new ArrayList(); - - // The best local candidate we have offered (and accepted by the other part) - private TransportCandidate acceptedLocalCandidate; - - // The thread that will report the result to the other end - private Thread resultThread; - - // Listener for the resolver - private TransportResolverListener.Resolver resolverListener; - - // states - final Inviting inviting; - - final Accepting accepting; - - final Pending pending; - - final Active active; - - /** - * Default constructor. - * - * @param js The Jingle session - * @param transResolver The TransportManager to use - */ - public TransportNegotiator(final JingleSession js, - final TransportResolver transResolver) { - super(js.getConnection()); - - session = js; - resolver = transResolver; - - resultThread = null; - - // Create the states... - inviting = new Inviting(this); - accepting = new Accepting(this); - pending = new Pending(this); - active = new Active(this); - } - - /** - * Get a new instance of the right JingleTransport class with this - * candidate. - * - * @return A JingleTransport instance - */ - protected abstract JingleTransport getJingleTransport(TransportCandidate cand); - - /** - * Return true if the transport candidate is acceptable for the current - * negotiator. - * - * @return true if the transport candidate is acceptable - */ - protected abstract boolean acceptableTransportCandidate(TransportCandidate tc); - - /** - * Obtain the best local candidate we want to offer. - * - * @return the best local candidate - */ - public TransportCandidate getBestLocalCandidate() { - return resolver.getPreferredCandidate(); - } - - /** - * Set the best local transport candidate we have offered and accepted by - * the other endpoint. - * - * @param acceptedLocalCandidate the acceptedLocalCandidate to set - */ - protected void setAcceptedLocalCandidate(final TransportCandidate bestLocalCandidate) - throws XMPPException { - if (resolver.getCandidatesList().contains(bestLocalCandidate)) { - acceptedLocalCandidate = bestLocalCandidate; - } else { - throw new XMPPException("Local transport candidate has not be offered."); - } - } - - /** - * Get the best accepted local candidate we have offered. - * - * @return a transport candidate we have offered. - */ - public TransportCandidate getAcceptedLocalCandidate() { - return acceptedLocalCandidate; - } - - /** - * Obtain the best common transport candidate obtained in the negotiation. - * - * @return the bestRemoteCandidate - */ - public abstract TransportCandidate getBestRemoteCandidate(); - - /** - * Get the list of remote candidates. - * - * @return the remoteCandidates - */ - public List getRemoteCandidates() { - return remoteCandidates; - } - - /** - * Add a remote candidate to the list. The candidate will be checked in - * order to verify if it is usable. - * - * @param rc a remote candidate to add and check. - */ - public void addRemoteCandidate(final TransportCandidate rc) { - // Add the candidate to the list - if (rc != null) { - if (acceptableTransportCandidate(rc)) { - synchronized (remoteCandidates) { - remoteCandidates.add(rc); - } - - // Check if the new candidate can be used. - checkRemoteCandidate(rc); - } - } - } - - /** - * Add a offered candidate to the list. - * - * @param rc a remote candidate we have offered. - */ - public void addOfferedCandidate(final TransportCandidate rc) { - // Add the candidate to the list - if (rc != null) { - synchronized (offeredCandidates) { - offeredCandidates.add(rc); - } - } - } - - /** - * Check asynchronously the new transport candidate. - * - * @param offeredCandidate a transport candidates to check - */ - protected void checkRemoteCandidate(final TransportCandidate offeredCandidate) { - resolver.addListener(new TransportResolverListener.Checker() { - public void candidateChecked(final TransportCandidate cand, - final boolean validCandidate) { - if (validCandidate) { - addValidRemoteCandidate(offeredCandidate); - } - } - }); - resolver.check(offeredCandidate); - } - - /** - * Return true if the transport is established. - * - * @return true if the transport is established. - */ - public boolean isEstablished() { - return getBestRemoteCandidate() != null && getAcceptedLocalCandidate() != null; - } - - /** - * Return true if the transport is fully established. - * - * @return true if the transport is fully established. - */ - public boolean isFullyEstablished() { - return isEstablished() && getState() == active; - } - - /** - * Launch a thread that checks, after some time, if any of the candidates - * offered by the other endpoint is usable. The thread does not check the - * candidates: it just checks if we have got a valid one and sends an Accept - * in that case. - */ - private void delayedCheckBestCandidate(final JingleSession js, final Jingle jin) { - // - // If this is the first insertion in the list, start the thread that - // will send the result of our checks... - // - if (resultThread == null && !getRemoteCandidates().isEmpty()) { - resultThread = new Thread(new Runnable() { - public void run() { - - // Sleep for some time, waiting for the candidates checks - try { - Thread.sleep(CANDIDATES_ACCEPT_PERIOD - + TransportResolver.CHECK_TIMEOUT); - } catch (InterruptedException e) { - } - - // Once we are in pending state, look for any valid remote - // candidate, and send an "accept" if we have one... - TransportCandidate bestRemote = getBestRemoteCandidate(); - State state = getState(); - - if (bestRemote != null && (state == pending || state == active)) { - // Accepting the remote candidate - Jingle jout = new Jingle(Jingle.Action.TRANSPORTACCEPT); - jout.addTransport(getJingleTransport(bestRemote)); - - // Send the packet - js.sendFormattedJingle(jin, jout); - - if (isEstablished()) { - setState(active); - } - } - } - }, "Waiting for all the transport candidates checks..."); - - resultThread.setName("Transport Resolver Result"); - resultThread.start(); - } - } - - /** - * Add a valid remote candidate to the list. The remote candidate has been - * checked, and the remote - * - * @param remoteCandidate a remote candidate to add - */ - public void addValidRemoteCandidate(final TransportCandidate remoteCandidate) { - // Add the candidate to the list - if (remoteCandidate != null) { - synchronized (validRemoteCandidates) { - validRemoteCandidates.add(remoteCandidate); - } - } - } - - /** - * Get the list of valid (ie, checked) remote candidates. - * - * @return The list of valid (ie, already checked) remote candidates. - */ - public ArrayList getValidRemoteCandidatesList() { - synchronized (validRemoteCandidates) { - return new ArrayList(validRemoteCandidates); - } - } - - /** - * Get an iterator for the list of valid (ie, checked) remote candidates. - * - * @return The iterator for the list of valid (ie, already checked) remote - * candidates. - */ - public Iterator getValidRemoteCandidates() { - return Collections.unmodifiableList(getRemoteCandidates()).iterator(); - } - - /** - * Add an offered remote candidate. The transport candidate can be unusable: - * we must check if we can use it. - * - * @param rc the remote candidate to add. - */ - public void addRemoteCandidates(final List rc) { - if (rc != null) { - if (rc.size() > 0) { - Iterator iter = rc.iterator(); - while (iter.hasNext()) { - addRemoteCandidate((TransportCandidate) iter.next()); - } - } - } - } - - /** - * Parse the list of transport candidates from a Jingle packet. - * - * @param jin The input jingle packet - */ - private ArrayList obtainCandidatesList(final Jingle jin) { - ArrayList result = new ArrayList(); - - if (jin != null) { - // Get the list of candidates from the packet - Iterator iTrans = jin.getTransports(); - while (iTrans.hasNext()) { - JingleTransport trans = (JingleTransport) iTrans.next(); - - Iterator iCand = trans.getCandidates(); - while (iCand.hasNext()) { - JingleTransportCandidate cand = (JingleTransportCandidate) iCand - .next(); - TransportCandidate transCand = cand.getMediaTransport(); - result.add(transCand); - } - } - } - - return result; - } - - final private boolean isOfferStarted() { - return resolver.isResolving() || resolver.isResolved(); - } - - /** - * Send an offer for a transport candidate - * - * @param cand - */ - private synchronized void sendTransportCandidateOffer(final TransportCandidate cand) { - if (!cand.isNull()) { - addOfferedCandidate(cand); - - // Offer our new candidate... - session.sendFormattedJingle(new Jingle(getJingleTransport(cand))); - } - } - - /** - * Create a Jingle packet where we announce our transport candidates. - * - * @throws XMPPException - */ - protected void sendTransportCandidatesOffer() throws XMPPException { - List notOffered = resolver.getCandidatesList(); - notOffered.removeAll(offeredCandidates); - - // Send any unset candidate - Iterator iter = notOffered.iterator(); - while (iter.hasNext()) { - sendTransportCandidateOffer((TransportCandidate) iter.next()); - } - - // .. and start a listener that will send any future candidate - if (resolverListener == null) { - // Add a listener that sends the offer when the resolver finishes... - resolverListener = new TransportResolverListener.Resolver() { - public void candidateAdded(final TransportCandidate cand) { - sendTransportCandidateOffer(cand); - } - - public void end() { - } - - public void init() { - } - }; - - resolver.addListener(resolverListener); - } - - if (!(resolver.isResolving() || resolver.isResolved())) { - // Resolve our IP and port - resolver.resolve(); - } - } - - /** - * Dispatch an incoming packet. The method is responsible for recognizing - * the packet type and, depending on the current state, deliverying the - * packet to the right event handler and wait for a response. - * - * @param iq the packet received - * @return the new Jingle packet to send. - * @throws XMPPException - */ - public IQ dispatchIncomingPacket(final IQ iq, final String id) throws XMPPException { - IQ jout = null; - - if (invalidState()) { - if (iq == null) { - // With a null packet, we are just inviting the other end... - setState(inviting); - jout = getState().eventInvite(); - - } else { - if (iq instanceof Jingle) { - // If there is no specific media action associated, then we - // are being invited to a new session... - setState(accepting); - jout = getState().eventInitiate((Jingle) iq); - } else { - throw new IllegalStateException( - "Invitation IQ received is not a Jingle packet in Transport negotiator."); - } - } - } else { - if (iq == null) { - return null; - } else { - if (iq.getType().equals(IQ.Type.ERROR)) { - // Process errors - getState().eventError(iq); - } else if (iq.getType().equals(IQ.Type.RESULT)) { - // Process ACKs - if (isExpectedId(iq.getPacketID())) { - jout = getState().eventAck(iq); - removeExpectedId(iq.getPacketID()); - } - } else if (iq instanceof Jingle) { - // Get the action from the Jingle packet - Jingle jin = (Jingle) iq; - Jingle.Action action = jin.getAction(); - - if (action != null) { - if (action.equals(Jingle.Action.TRANSPORTACCEPT)) { - jout = getState().eventAccept(jin); - } else if (action.equals(Jingle.Action.TRANSPORTDECLINE)) { - jout = getState().eventDecline(jin); - } else if (action.equals(Jingle.Action.TRANSPORTINFO)) { - jout = getState().eventInfo(jin); - } else if (action.equals(Jingle.Action.TRANSPORTMODIFY)) { - jout = getState().eventModify(jin); - } - } - } - } - } - - // Save the Id for any ACK - if (id != null) { - addExpectedId(id); - } else { - if (jout != null) { - addExpectedId(jout.getPacketID()); - } - } - - return jout; - } - - /** - * Trigger a session established event. - * - * @param best payload type that has been agreed. - */ - protected void triggerTransportEstablished(final TransportCandidate local, - final TransportCandidate remote) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Transport) { - JingleListener.Transport mli = (JingleListener.Transport) li; - mli.transportEstablished(local, remote); - } - } - } - - /** - * Trigger a media closed event. - * - * @param currPt current payload type that is cancelled. - */ - protected void triggerTransportClosed(final TransportCandidate cand) { - ArrayList listeners = getListenersList(); - Iterator iter = listeners.iterator(); - while (iter.hasNext()) { - JingleListener li = (JingleListener) iter.next(); - if (li instanceof JingleListener.Transport) { - JingleListener.Transport mli = (JingleListener.Transport) li; - mli.transportClosed(cand); - } - } - } - - // States - - /** - * First stage when we send a session request. - */ - public class Inviting extends JingleNegotiator.State { - - public Inviting(final TransportNegotiator neg) { - super(neg); - } - - /** - * Create an initial Jingle packet with an empty transport. - */ - public Jingle eventInvite() { - return new Jingle(getJingleTransport(null)); - } - - /** - * We have received some candidates. This can happen _before_ the ACK - * has been recieved... - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventInfo(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventInfo(final Jingle jin) throws XMPPException { - // Parse the Jingle and get any proposed transport candidates - addRemoteCandidates(obtainCandidatesList(jin)); - - // Wait for some time and check if we have a valid candidate to - // use... - delayedCheckBestCandidate(session, jin); - - return super.eventInfo(jin); - } - - /** - * The other endpoint has partially accepted our invitation: start - * offering a list of candidates. - * - * @return an IQ packet - * @throws XMPPException - */ - public Jingle eventAck(final IQ iq) throws XMPPException { - sendTransportCandidatesOffer(); - setState(pending); - return super.eventAck(iq); - } - } - - /** - * We are accepting connections. This is the starting state when we accept a - * connection... - */ - public class Accepting extends JingleNegotiator.State { - public Accepting(final TransportNegotiator neg) { - super(neg); - } - - /** - * We have received an invitation. The packet will be ACKed by lower - * levels... - */ - public Jingle eventInitiate(final Jingle jin) throws XMPPException { - // Parse the Jingle and get any proposed transport candidates - addRemoteCandidates(obtainCandidatesList(jin)); - - // Start offering candidates - sendTransportCandidatesOffer(); - - // All these candidates will be checked asyncronously. Wait for some - // time and check if we have a valid candidate to use... - delayedCheckBestCandidate(session, jin); - - // Set the next state - setState(pending); - - return super.eventInitiate(jin); - } - } - - /** - * We are still receiving candidates - */ - public class Pending extends JingleNegotiator.State { - - public Pending(final TransportNegotiator neg) { - super(neg); - } - - /** - * One of our transport candidates has been accepted. - * - * @param jin The input packet - * @return a Jingle packet - * @throws XMPPException an exception - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventAccept(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventAccept(final Jingle jin) throws XMPPException { - Jingle response = null; - - // Parse the Jingle and get the accepted candidate - ArrayList accepted = obtainCandidatesList(jin); - if (!accepted.isEmpty()) { - TransportCandidate cand = (TransportCandidate) accepted.get(0); - - setAcceptedLocalCandidate(cand); - - if (isEstablished()) { - setState(active); - } - } - return response; - } - - /** - * We have received another remote transport candidates. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventInfo(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventInfo(final Jingle jin) throws XMPPException { - - sendTransportCandidatesOffer(); - - // Parse the Jingle and get any proposed transport candidates - addRemoteCandidates(obtainCandidatesList(jin)); - - // Wait for some time and check if we have a valid candidate to - // use... - delayedCheckBestCandidate(session, jin); - - return super.eventInfo(jin); - } - - /** - * None of our transport candidates has been accepted... - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventDecline(org.jivesoftware.smackx.packet.Jingle) - */ - public Jingle eventDecline(final Jingle inJingle) throws JingleException { - throw new JingleException("No common payload found."); - } - } - - /** - * "Active" state: we have an agreement about the codec... - */ - public class Active extends JingleNegotiator.State { - - public Active(final TransportNegotiator neg) { - super(neg); - } - - /** - * We have an agreement. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventEnter() { - triggerTransportEstablished(getAcceptedLocalCandidate(), - getBestRemoteCandidate()); - super.eventEnter(); - } - - /** - * We have finished the transport. - * - * @see org.jivesoftware.smackx.jingle.JingleNegotiator.State#eventEnter() - */ - public void eventExit() { - triggerTransportClosed(null); - super.eventExit(); - } - } - - // Subclasses - - /** - * Raw-UDP transport negotiator - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ - public static class RawUdp extends TransportNegotiator { - - /** - * Default constructor, with a JingleSession and transport manager. - * - * @param js The Jingle session this negotiation belongs to. - * @param res The transport resolver to use. - */ - public RawUdp(final JingleSession js, final TransportResolver res) { - super(js, res); - } - - /** - * Get a JingleTransport instance. - */ - protected JingleTransport getJingleTransport(final TransportCandidate bestRemote) { - JingleTransport.RawUdp jt = new JingleTransport.RawUdp(); - jt.addCandidate(new JingleTransport.RawUdp.Candidate(bestRemote)); - return jt; - } - - /** - * Obtain the best common transport candidate obtained in the - * negotiation. - * - * @return the bestRemoteCandidate - */ - public TransportCandidate getBestRemoteCandidate() { - // Hopefully, we only have one validRemoteCandidate - ArrayList cands = getValidRemoteCandidatesList(); - if (!cands.isEmpty()) { - return (TransportCandidate) cands.get(0); - } else { - return null; - } - } - - /** - * Return true for fixed candidates. - */ - protected boolean acceptableTransportCandidate(final TransportCandidate tc) { - return tc instanceof TransportCandidate.Fixed; - } - } - - /** - * Ice transport negotiator. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ - public static class Ice extends TransportNegotiator { - - /** - * Default constructor, with a JingleSession and transport manager. - * - * @param js The Jingle session this negotiation belongs to. - * @param res The transport manager to use. - */ - public Ice(final JingleSession js, final TransportResolver res) { - super(js, res); - } - - /** - * Get a JingleTransport instance. - * - * @param bestRemote - */ - protected JingleTransport getJingleTransport(final TransportCandidate bestRemote) { - JingleTransport.Ice jt = new JingleTransport.Ice(); - jt.addCandidate(new JingleTransport.Ice.Candidate(bestRemote)); - return jt; - } - - /** - * Obtain the best remote candidate obtained in the negotiation so far. - * - * @return the bestRemoteCandidate - */ - public TransportCandidate getBestRemoteCandidate() { - TransportCandidate.Ice result = null; - - ArrayList cands = getValidRemoteCandidatesList(); - if (!cands.isEmpty()) { - Collections.sort(cands); - // Return the last candidate - result = (TransportCandidate.Ice) cands.get(cands.size() - 1); - } - - return result; - } - - /** - * Return true for ICE candidates. - */ - protected boolean acceptableTransportCandidate(final TransportCandidate tc) { - return tc instanceof TransportCandidate.Ice; - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJMFMediaEngine.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJMFMediaEngine.java deleted file mode 100644 index 9f8776d61..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJMFMediaEngine.java +++ /dev/null @@ -1,131 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Set; - -import javax.media.Controller; -import javax.media.Manager; -import javax.media.NoProcessorException; -import javax.media.Processor; -import javax.media.control.TrackControl; -import javax.media.format.AudioFormat; -import javax.media.protocol.DataSource; -import javax.sound.sampled.AudioInputStream; - -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaManager.ContentType; -import org.jivesoftware.smackx.jingle.media.util.FormatTranslator; -import org.jivesoftware.smackx.jingle.media.util.StreamConverter; - -public class DecodingJMFMediaEngine extends MediaEngine.Decoding { - - private InputStream input; - private AudioInputStream aisOutput; - - private Processor processor; - - public DecodingJMFMediaEngine() { - super(null); - } - - public DecodingJMFMediaEngine(PayloadType inputFormat) { - super(inputFormat); - } - - public Set getSupportedPayloadTypes(ContentType contentType) { - if(contentType == ContentType.AUDIO) { - Set result = new HashSet(); - - for(int i = 0; i < EncodingJMFMediaEngine.supported.length; i++) { - - PayloadType pt = FormatTranslator.toPayloadType(EncodingJMFMediaEngine.supported[i]); - if(pt!=null) result.add(pt); - } - - return result; - } - return null; - } - - public void start() { - processor.start(); - - } - - public void stop() { - processor.stop(); - } - - public void configure() { - - if(input == null) throw new InputNotSetError("Input must be set before configuring."); - DataSource inputDS = StreamConverter.toDataSource(input); - - try { - processor = Manager.createProcessor(inputDS); - - processor.configure(); - waitForState(Processor.Configured, processor); - - TrackControl[] tracks = processor.getTrackControls(); - - tracks[0].setFormat(new AudioFormat(AudioFormat.LINEAR, 44100.0, 16, 2)); - - processor.realize(); - - } catch (NoProcessorException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - public int getState() { - if(processor == null) return INSTANTIATED; - else if(processor.getState() == Processor.Configuring || - processor.getState() == Processor.Configured || - processor.getState() == Controller.Realizing) return CONFIGURING; - else if(processor.getState() == Controller.Realized) return CONFIGURED; - else if(processor.getState() == Controller.Started) return STARTED; - else return INSTANTIATED; - } - - public void close() { - processor.close(); - processor = null; - try { - getOutput().close(); - } catch (IOException e) {} - } - - public InputStream getOutput() { - if(processor == null || (processor.getState() != Processor.Realized && processor.getState() != Processor.Started)) aisOutput = null; - else if(aisOutput == null) aisOutput = StreamConverter.toAudioInputStream(processor.getDataOutput()); - - return aisOutput; - } - - /** - * Block until processor p enters the given state. - */ - private void waitForState(int state, Processor p){ - while(p.getState() != state) { - try { - Thread.sleep(10); - } catch (InterruptedException e) {} - } - } - - public InputStream getInput() { - return input; - } - - public void setInput(InputStream input) { - if(processor == null) this.input = input; - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJSMediaEngine.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJSMediaEngine.java deleted file mode 100644 index 131907d77..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/DecodingJSMediaEngine.java +++ /dev/null @@ -1,134 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Set; - -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; - -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaManager.ContentType; -import org.jivesoftware.smackx.jingle.media.util.FormatTranslator; - -public class DecodingJSMediaEngine extends MediaEngine.Decoding { - - private static AudioFormat[] defaultOutputs = {new AudioFormat(8000, 8, 1, true, false), - new AudioFormat(16000, 8, 1, true, false), - new AudioFormat(44100, 8, 1, true, false), - new AudioFormat(8000, 8, 2, true, false), - new AudioFormat(16000, 8, 2, true, false), - new AudioFormat(44100, 8, 2, true, false), - new AudioFormat(8000, 16, 1, true, false), - new AudioFormat(16000, 16, 1, true, false), - new AudioFormat(44100, 16, 1, true, false), - new AudioFormat(8000, 16, 2, true, false), - new AudioFormat(16000, 16, 2, true, false), - new AudioFormat(44100, 16, 2, true, false)}; - - private AudioInputStream input, output; - private AudioFormat format; - private int state; - - - /** - * Zero argument constructor demanded by the SPI. Should not normally be used. - */ - public DecodingJSMediaEngine() { - super(null); - } - - public DecodingJSMediaEngine(PayloadType inputFormat) { - super(inputFormat); - format = FormatTranslator.toJSAudioFormat(inputFormat); - state = INSTANTIATED; - } - - public synchronized InputStream getInput() { - return input; - } - - public synchronized void setInput(InputStream input) { - try { - AudioInputStream aIS; - if(input instanceof AudioInputStream) aIS = (AudioInputStream) input; - else aIS = AudioSystem.getAudioInputStream(input); - - if(!FormatTranslator.equals(aIS.getFormat(),format)) throw new IllegalArgumentException("Incoming " + - "audio stream does not have the correct format. Expected "+ format +" and got " + - aIS.getFormat()); - this.input = aIS; - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - - } - - public synchronized InputStream getOutput() { - return output; - } - - public synchronized Set getSupportedPayloadTypes(ContentType contentType) { - Set result = new HashSet(); - - if(contentType.equals(ContentType.AUDIO)) { - - for(int i = 0; i < defaultOutputs.length; i++) { - AudioFormat outputFormat = defaultOutputs[i]; - - AudioFormat.Encoding[] encodings = AudioSystem.getTargetEncodings(outputFormat); - - for(int j = 0; j < encodings.length; j++) { - - AudioFormat[] formats = AudioSystem.getTargetFormats(encodings[j], outputFormat); - for(int k = 0; k < formats.length; k++) { - - if(AudioSystem.isConversionSupported(AudioFormat.Encoding.PCM_SIGNED, formats[k]) && FormatTranslator.toPayloadType(formats[k]) != null) - result.add(FormatTranslator.toPayloadType(formats[k])); - } - } - } - - } - - return result; - } - - public synchronized int getState() { - return state; - } - - public synchronized void configure() throws UnableToConfigureMediaEngine { - if(state != INSTANTIATED) throw new StateOrderViolationError("MediaEngine should be in the instantiated state when configure is called."); - if(input == null) throw new InputNotSetError("Must set input before configuring MediaEngine."); - output = AudioSystem.getAudioInputStream(AudioFormat.Encoding.PCM_SIGNED, input); - state = CONFIGURED; - } - - public synchronized void start() { - if(state == CONFIGURED) state = STARTED; - else throw new StateOrderViolationError("Tried to start MediaEngine without configuring first."); - } - - public synchronized void stop() { - if(state == STARTED) state = CONFIGURED; - else throw new StateOrderViolationError("Tried to stop MediaEngine when it hasn't been started."); - } - - public synchronized void close() { - try { - if(output != null) { - output.close(); - output = null; - } - state = CLOSED; - } catch (IOException e) { - e.printStackTrace(); - } - } - - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJMFMediaEngine.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJMFMediaEngine.java deleted file mode 100644 index a05df1207..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJMFMediaEngine.java +++ /dev/null @@ -1,194 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Set; - -import javax.media.Controller; -import javax.media.Manager; -import javax.media.NoProcessorException; -import javax.media.Processor; -import javax.media.control.TrackControl; -import javax.media.format.AudioFormat; -import javax.media.protocol.DataSource; -import javax.sound.sampled.AudioInputStream; - -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaManager.ContentType; -import org.jivesoftware.smackx.jingle.media.util.FormatTranslator; -import org.jivesoftware.smackx.jingle.media.util.StreamConverter; - -public class EncodingJMFMediaEngine extends MediaEngine.Encoding { - - protected static final AudioFormat[] supported = { - new AudioFormat(AudioFormat.LINEAR, 44100.0, 16, 2, AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, byte[].class), - new AudioFormat(AudioFormat.LINEAR, 44100.0, 16, 1, AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, byte[].class) - }; - - private Processor processor; - private InputStream input; - private AudioInputStream aisOutput; - - public EncodingJMFMediaEngine() { - super(null); - } - - public EncodingJMFMediaEngine(PayloadType outputFormat) { - super(outputFormat); - } - - public Set getSupportedPayloadTypes(ContentType contentType) { - if(contentType == ContentType.AUDIO) { - Set result = new HashSet(); - - for(int i = 0; i < supported.length; i++) { - - PayloadType pt = FormatTranslator.toPayloadType(supported[i]); - if(pt!=null) result.add(pt); - } - - return result; - } - return null; -// //first check the cache -// Map cachedResultByDS = (Map) supportedPTs.get(StreamConverter.toDataSource(getInput())); -// if(cachedResultByDS != null) { -// Set cachedResultByContentType = (Set) cachedResultByDS.get(contentType); -// if(cachedResultByContentType != null) return cachedResultByContentType; -// } -// -// -// // currently only supports audio -// if(contentType.equals(ContentType.AUDIO)) { -// if(getInput() == null) throw new MediaEngine.InputNotSetError("Must set input before" + -// " asking which formats it supports."); -// -// DataSource inputDS = StreamConverter.toDataSource(input); -// -// -// //this is a little bit of a hack, but it beats hard coding it. -// Processor p; -// try { -// p = Manager.createProcessor(inputDS); -// p.configure(); -// -// waitForState(Processor.Configured, p); -// -// TrackControl[] tracks = p.getTrackControls(); -// -// ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.CONTENT_UNKNOWN); -// p.setContentDescriptor(cd); -// -// Format[] formats = tracks[0].getSupportedFormats(); -// Set result = new HashSet(); -// -// for(int i = 0; i < formats.length; i++) { -// PayloadType pt = FormatTranslator.toPayloadType(formats[i]); -// if(pt!=null)System.out.println(formats[i] + " - " + pt.getName() + ", " + pt.getChannels() + ", " + pt.getId()); -// if(pt!=null) result.add(pt); -// } -// -// //add the result to the cache -// if(cachedResultByDS != null) cachedResultByDS.put(contentType, result); -// else { -// Map newCTMap = new HashMap(); -// newCTMap.put(contentType, result); -// supportedPTs.put(inputDS, newCTMap); -// } -// -// return result; -// -// } catch (Exception e) { -// //not sure if much more can be done here. -// e.printStackTrace(); -// } -// -// } -// return null; - } - - public void configure() throws UnableToConfigureMediaEngine { - - DataSource inputDS = StreamConverter.toDataSource(input); - - if(inputDS == null) throw new InputNotSetError("Input must be set before configuring."); - - try { - processor = Manager.createProcessor(inputDS); - - processor.configure(); - waitForState(Processor.Configured, processor); - - TrackControl[] tracks = processor.getTrackControls(); - try { - tracks[0].setFormat(FormatTranslator.toJMFFormat(getPayloadType())); - } catch (Exception e) { - throw new UnableToConfigureMediaEngine(e); - } - - processor.realize(); - - } catch (NoProcessorException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - public void start() { - processor.start(); - } - - public void stop() { - processor.stop(); - - } - - public int getState() { - if(processor == null) return INSTANTIATED; - else if(processor.getState() == Processor.Configuring || - processor.getState() == Processor.Configured || - processor.getState() == Controller.Realizing) return CONFIGURING; - else if(processor.getState() == Controller.Realized) return CONFIGURED; - else if(processor.getState() == Controller.Started) return STARTED; - else return INSTANTIATED; - } - - public void close() { - processor.close(); - processor = null; - try { - getOutput().close(); - } catch (IOException e) {} - } - - /** - * Block until processor p enters the given state. - */ - private void waitForState(int state, Processor p){ - while(p.getState() != state) { - try { - Thread.sleep(10); - } catch (InterruptedException e) {} - } - } - - public InputStream getOutput() { - if(processor == null || (processor.getState() != Processor.Realized && processor.getState() != Processor.Started)) aisOutput = null; - else if(aisOutput == null) aisOutput = StreamConverter.toAudioInputStream(processor.getDataOutput()); - - return aisOutput; - } - - public InputStream getInput() { - return input; - } - - public void setInput(InputStream input) { - if(processor == null) this.input = input; - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJSMediaEngine.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJSMediaEngine.java deleted file mode 100644 index c765e09ba..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/EncodingJSMediaEngine.java +++ /dev/null @@ -1,111 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashSet; -import java.util.Set; - -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; - -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaManager.ContentType; -import org.jivesoftware.smackx.jingle.media.util.FormatTranslator; - -public class EncodingJSMediaEngine extends MediaEngine.Encoding { - - private AudioInputStream input, output; - private AudioFormat format; - private int state; - - /** - * Zero argument constructor demanded by the SPI. Should not normally be used. - */ - public EncodingJSMediaEngine() { - super(null); - } - - public EncodingJSMediaEngine(PayloadType outputFormat) { - super(outputFormat); - format = FormatTranslator.toJSAudioFormat(outputFormat); - state = INSTANTIATED; - } - - public synchronized InputStream getInput() { - return input; - } - - public synchronized void setInput(InputStream input) { - try { - - AudioInputStream aIS; - if(input instanceof AudioInputStream) aIS = (AudioInputStream) input; - else aIS = AudioSystem.getAudioInputStream(input); - - if((aIS.getFormat().getEncoding().equals(AudioFormat.Encoding.PCM_SIGNED)) - || (aIS.getFormat().getEncoding().equals(AudioFormat.Encoding.PCM_UNSIGNED))) - this.input = aIS; - - else throw new IllegalArgumentException("Input to EncodingJSMediaEngine should be PCM."); - - } catch (Exception e) { - throw new IllegalArgumentException(e); - } - } - - public synchronized InputStream getOutput() { - return output; - } - - public synchronized Set getSupportedPayloadTypes(ContentType contentType) { - if(input == null) throw new InputNotSetError("Input must be set before calling getSupportedPayloadTypes."); - Set result = new HashSet(); - - if(contentType.equals(ContentType.AUDIO)) { - AudioFormat.Encoding[] encodings = AudioSystem.getTargetEncodings(input.getFormat()); - - for(int i = 0; i < encodings.length; i++) { - AudioFormat[] formats = AudioSystem.getTargetFormats(encodings[i], input.getFormat()); - for(int j = 0; j < formats.length; j++) - if(FormatTranslator.toPayloadType(formats[j]) != null) - result.add(FormatTranslator.toPayloadType(formats[j])); - } - } - return result; - } - - public synchronized int getState() { - return state; - } - - public synchronized void configure() throws UnableToConfigureMediaEngine { - if(input == null) throw new InputNotSetError("Must set input before configuring MediaEngine."); - if(state != INSTANTIATED) throw new StateOrderViolationError("MediaEngine should be in the instantiated state when configure is called."); - output = AudioSystem.getAudioInputStream(format, input); - state = CONFIGURED; - } - - public synchronized void start() { - if(state == CONFIGURED) state = STARTED; - else throw new StateOrderViolationError("Tried to start MediaEngine without configuring first."); - } - - public synchronized void stop() { - if(state == STARTED) state = CONFIGURED; - else throw new StateOrderViolationError("Tried to stop MediaEngine when it hasn't been started."); - } - - public synchronized void close() { - try { - if(output != null) { - output.close(); - output = null; - } - state = CLOSED; - } catch (IOException e) { - e.printStackTrace(); - } - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JMFMediaTransport.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JMFMediaTransport.java deleted file mode 100644 index 20510873d..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JMFMediaTransport.java +++ /dev/null @@ -1,152 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.IOException; -import java.io.InputStream; -import java.net.InetAddress; -import java.util.HashSet; -import java.util.Set; - -import javax.media.protocol.DataSource; -import javax.media.rtp.RTPManager; -import javax.media.rtp.ReceiveStream; -import javax.media.rtp.ReceiveStreamListener; -import javax.media.rtp.SendStream; -import javax.media.rtp.SessionAddress; -import javax.media.rtp.event.NewReceiveStreamEvent; -import javax.media.rtp.event.ReceiveStreamEvent; - -import org.jivesoftware.smackx.jingle.media.util.StreamConverter; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportCandidate.Protocol; - -/** - * JMF based subclass of the abstract MediaTransport class. This class presently only supports - * sending via UDP. - * - * @author Alasdair North - * - */ -public class JMFMediaTransport extends MediaTransport implements ReceiveStreamListener { - - private RTPManager rtpManager; - private int receivingState, transmittingState; - private SendStream sendStream; - private ReceiveStream receiveStream; - private InputStream inputStream, outputStream; - private DataSource input; - - public JMFMediaTransport(TransportCandidate remoteCandidate, TransportCandidate localCandidate) { - super(remoteCandidate, localCandidate); - rtpManager = RTPManager.newInstance(); - transmittingState = MediaTransport.TRANSMITTER_INSTANTIATED; - receivingState = MediaTransport.RECEIVER_INSTANTIATED; - } - - public void configure() { - if(getInput() == null) throw new UnableToConfigure("Tried to configure with input not set."); - - try { - SessionAddress localAddr = new SessionAddress(InetAddress.getByName( - getLocalCandidate().getIP()), getLocalCandidate().getPort()); - rtpManager.initialize(localAddr); - rtpManager.addTarget(new SessionAddress(InetAddress.getByName( - getRemoteCandidate().getIP()), getRemoteCandidate().getPort())); - - transmittingState = MediaTransport.TRANSMITTER_CONFIGURED; - receivingState = MediaTransport.RECEIVER_CONFIGURED; - } catch (Exception e) { - throw new UnableToConfigure(e); - } - } - - public void start() { - //start listening for incoming streams - rtpManager.addReceiveStreamListener(this); - receivingState = MediaTransport.RECEIVER_WAITING; - - //and start sending - try { - sendStream = rtpManager.createSendStream(input, 0); - sendStream.start(); - transmittingState = MediaTransport.TRANSMITTER_SENDING; - - } catch (Exception e) { - throw new UnableToStart(e); - } - } - - public void stop() { - try { - sendStream.stop(); - transmittingState = MediaTransport.TRANSMITTER_CONFIGURED; - rtpManager.removeReceiveStreamListener(this); - receivingState = MediaTransport.RECEIVER_CONFIGURED; - } catch (IOException e) { - e.printStackTrace(); - } - - } - - public void close() { - try { - sendStream.stop(); - sendStream = null; - receiveStream = null; - rtpManager.dispose(); - rtpManager = null; - - } catch (IOException e) { - e.printStackTrace(); - } - } - - public int getTransmitterState() { - return transmittingState; - } - - public int getReceiverState() { - return receivingState; - } - - public void update(ReceiveStreamEvent evt) { - if (evt instanceof NewReceiveStreamEvent && receiveStream ==null) { - - try { - receiveStream = ((NewReceiveStreamEvent)evt).getReceiveStream(); - receivingState = MediaTransport.RECEIVER_RECEIVING; - notifyOutputListenersOutputReady(getOutput()); - - } catch (Exception e) { - e.printStackTrace(); - } - } - //TODO deal with disconnection - - } - - public InputStream getOutput() { - if(receiveStream == null) return null; - if(outputStream == null) outputStream = StreamConverter.toAudioInputStream(receiveStream.getDataSource()); - - return outputStream; - } - - public Set getSupportedProtocols() { - Set result = new HashSet(); - - result.add(Protocol.UDP); - - return null; - } - - public InputStream getInput() { - return inputStream; - } - - public void setInput(InputStream input) { - this.input = StreamConverter.toDataSource(input); - inputStream = input; - - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaListener.java deleted file mode 100644 index 3cd463bf6..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaListener.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.InputStream; - -/** - * Jingle media listeners. - * - * @author Alasdair North - */ -public interface JingleMediaListener { - - /** - * Listen for when an objects output DataSource is ready to be used. - * @author Alasdair North - */ - public static interface Output { - - /** - * Called when the objects output has changed (but not when it changes to null). - * @param output the new output DataSource of the listened to object. - */ - public void outputChanged(InputStream output); - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaManager.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaManager.java deleted file mode 100644 index dd3bc66de..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaManager.java +++ /dev/null @@ -1,539 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.InputStream; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import javax.sound.sampled.AudioSystem; - -import org.jivesoftware.smack.XMPPConnection; -import org.jivesoftware.smackx.jingle.JingleListener; -import org.jivesoftware.smackx.jingle.JingleManager; -import org.jivesoftware.smackx.jingle.JingleSession; -import org.jivesoftware.smackx.jingle.JingleSessionRequest; -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.util.FormatTranslator; -import org.jivesoftware.smackx.nat.STUNResolver; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.nat.TransportResolver; -import org.jivesoftware.smackx.nat.TransportCandidate.Protocol; - -import sun.misc.Service; - -/** - * The JingleMediaManager is used to initiate peer-to-peer connections - * using the Jingle protocol (JEP-0166). - * - * @author Alasdair North - * - */ -public class JingleMediaManager { - - private JingleManager jingleManager; - private TransportSupportStore supportedTransports; - - private Class[] encodingMediaEngines, decodingMediaEngines, mediaTransports; - - //default lists to be used if none are found via the SPI - private static final Class[] defaultEME = {EncodingJMFMediaEngine.class, EncodingJSMediaEngine.class}; - private static final Class[] defaultDME = {DecodingJMFMediaEngine.class, DecodingJSMediaEngine.class}; - private static final Class[] defaultMT = {JMFMediaTransport.class}; - - private Comparator ptComparator; - - - /** - * Create a new JingleMediaManager. - * @param xmppConnection XMPPConnection that sessions will be negotiated over. - * @param tr TransportResolver to be used. - * @param ptComparator Comparator to be used when sorting PayloadTypes into order of preference. - */ - public JingleMediaManager(XMPPConnection xmppConnection, TransportResolver tr, Comparator ptComparator) { - jingleManager = new JingleManager(xmppConnection, tr); - JingleManager.setServiceEnabled(xmppConnection, true); - - this.ptComparator = ptComparator; - - //load the Classes for the media engines and media transports in the class path - Iterator itEnc = Service.providers(MediaEngine.Encoding.class); - encodingMediaEngines = getClassArray(itEnc); - if(encodingMediaEngines.length == 0) encodingMediaEngines = defaultEME; - - Iterator itDec = Service.providers(MediaEngine.Decoding.class); - decodingMediaEngines = getClassArray(itDec); - if(decodingMediaEngines.length == 0) decodingMediaEngines = defaultDME; - - Iterator itTran = Service.providers(MediaTransport.class); - mediaTransports = getClassArray(itTran); - if(mediaTransports.length == 0) mediaTransports = defaultMT; - - initializeSupportedTransports(); - } - - /** - * Create a new JingleMediaManager using the default PayloadType comparator (which prefers low - * bandwidth solutions). - * @param xmppConnection XMPPConnection that sessions will be negotiated over. - * @param tr TransportResolver to be used. - */ - public JingleMediaManager(XMPPConnection xmppConnection, TransportResolver tr) { - this(xmppConnection, tr, null); - setPTComparator(new DefaultPTC()); - } - - /** - * Create a new JingleMediaManager using the default PayloadType comparator (which prefers low - * bandwidth solutions) and TransportManager (which only negotiates UDP sessions). - * @param xmppConnection XMPPConnection that sessions will be negotiated over. - */ - public JingleMediaManager(XMPPConnection xmppConnection) { - this(xmppConnection, new STUNResolver()); - } - - /** - * Creates a JingleMediaSession to start communication with another user. - * @param JID the identity of the other user. - * @param contentType the desired content type of the session. - * @param input the source of data for the session. - * @return a JingleMediaSession object which will negotiate and implement a Jingle session. - */ - public JingleMediaSession createOutgoingJingleSession(String JID, ContentType contentType, - InputStream input) { - - if(contentType.equals(ContentType.AUDIO)) { - - JingleSession newSession = jingleManager.createOutgoingJingleSession(JID, - getSupportedPTs(contentType, input)); - try { - newSession.start(null); - return new JingleMediaSession(AudioSystem.getAudioInputStream(input), newSession, this); - } catch (Exception e) { - e.printStackTrace(); - } - } - return null; - } - - public JingleMediaSession createIncomingJingleSession(JingleSessionRequest request, ContentType contentType, InputStream input) { - - if(contentType.equals(ContentType.AUDIO)) { - - JingleSession js = jingleManager.createIncomingJingleSession(request, getSupportedPTs(contentType, input)); - - try { - js.start(null); - return new JingleMediaSession(AudioSystem.getAudioInputStream(input), js, this); - } catch (Exception e) { - e.printStackTrace(); - } - } - return null; - } - - /** - * Get a decoding MediaEngine for the specified PayloadType. - * @param pt type of input. - * @param input The InputStream containing the input for the MediaEngine. - * @return MediaEngine for decoding the given input. - */ - public MediaEngine.Decoding getDecodingMediaEngine(PayloadType pt, InputStream input) { - - return (MediaEngine.Decoding) getMediaEngine(false, pt, input); - } - - /** - * Get an encoding MediaEngine for the specified PayloadType. - * @param pt type of output desired. - * @param input The InputStream containing the input for the MediaEngine. - * @return MediaEngine for encoding the given input. - */ - public MediaEngine.Encoding getEncodingMediaEngine(PayloadType pt, InputStream input) { - - return (MediaEngine.Encoding) getMediaEngine(true, pt, input); - } - - private MediaEngine getMediaEngine(boolean encoding, PayloadType pt, InputStream input) { - - Class meClass; - EncodingSupportStore supportedPTs = generateSupportedAudioPTs(input); - - if(encoding) meClass = supportedPTs.getEncodingClassForPT(pt); - else meClass = supportedPTs.getDecodingClassForPT(pt); - - if(meClass != null) { - try { - - Object[] args = {pt}; - MediaEngine me = (MediaEngine) getInstance(meClass, args); - me.setInput(input); - return me; - - } catch (Exception e) { - // in this case there was something wrong with the instantiation - e.printStackTrace(); - return null; - } - } - return null; - } - - public List getSupportedPTs(ContentType contentType, InputStream input) { - - if(contentType.equals(ContentType.AUDIO)) { - - Set setPTs = generateSupportedAudioPTs(input) - .getSupportedPTsForContentType(contentType); - return order(setPTs); - } - return null; - } - - private List order(Set setPTs) { - List result = new ArrayList(setPTs); - Collections.sort(result, ptComparator); - return result; - } - - private EncodingSupportStore generateSupportedAudioPTs(InputStream input) { - EncodingSupportStore result = new EncodingSupportStore(); - addSupportedAudioPTs(true, input, result); - addSupportedAudioPTs(false, input, result); - return result; - } - - private void addSupportedAudioPTs(boolean encoding, - InputStream input, EncodingSupportStore store) { - - Class[] mediaEngineArray; - - if(encoding) mediaEngineArray = encodingMediaEngines; - else mediaEngineArray = decodingMediaEngines; - - for(int i = 0; i < mediaEngineArray.length; i++) { -// use reflection to instantiate a member of the class - try { - - Object[] args = {new PayloadType(PayloadType.INVALID_PT, "invalid"), this}; - MediaEngine me = (MediaEngine) getInstance(mediaEngineArray[i], args); - - if(encoding) me.setInput(input); - Set supported = me.getSupportedPayloadTypes(ContentType.AUDIO); - - Iterator it = supported.iterator(); - - while (it.hasNext()) { - if(encoding) store.setEncodingSupport(ContentType.AUDIO, - (PayloadType) it.next(), mediaEngineArray[i]); - else store.setDecodingSupport(ContentType.AUDIO, - (PayloadType) it.next(), mediaEngineArray[i]); - } - - } catch (Exception e) { -// Instantiation went wrong in some way. This can safely be ignored as the support -// elements will not have been added to the array. - e.printStackTrace(); - } - } - } - - private void initializeSupportedTransports() { - supportedTransports = new TransportSupportStore(); - - for(int i = 0; i < mediaTransports.length; i++) { - try { - Object[] args = {new TransportCandidate.Fixed()}; - MediaTransport mt = (MediaTransport) getInstance(mediaTransports[i], args); - - Set supported = mt.getSupportedProtocols(); - - Iterator it = supported.iterator(); - - while(it.hasNext()) supportedTransports.addElement(new TransportSupportElement( - (Protocol)it.next(), mediaTransports[i])); - - - } catch(Exception e) { -// Instantiation went wrong in some way. This can safely be ignored as the support -// elements will not have been added to the array. - e.printStackTrace(); - } - } - } - - /** - * Get a MediaTransport object that implements the given transport type. Returns null if none - * is availbale. - * @param remoteCandidate The remote candidate to use for connecting to the remote service. - * @param localCandidate The local candidate where we must listen for connections. - * @return MediaTransport object implementing transport of the given type. - */ - public MediaTransport getMediaTransport(TransportCandidate remoteCandidate, - TransportCandidate localCandidate) { - - Class mtClass = supportedTransports.getClassForProtocol(MediaTransport.getProtocol(remoteCandidate)); - - if(mtClass != null) { - try { - - Object[] args = {remoteCandidate, localCandidate}; - return (MediaTransport) getInstance(mtClass, args); - - } catch (Exception e) { - // instantiating the class did not work, so remove its pairing with this - // protocol from the list - supportedTransports.remove(MediaTransport.getProtocol(remoteCandidate), mtClass); - } - } - return null; - - } - - private Object getInstance(Class c, Object[] args) throws SecurityException, - NoSuchMethodException, IllegalArgumentException, InstantiationException, - IllegalAccessException, InvocationTargetException { - - Class[] argTypes = new Class[args.length]; - for(int i = 0; i < args.length; i++) argTypes[i] = args[i].getClass(); - Constructor con = c.getConstructor(argTypes); - - return con.newInstance(args); - - } - - /** - * Add a new session request listener. This listener will be notified when new session requests - * are received. - * @param listener the listener to be added. - */ - public void addSessionRequestListener(JingleListener.SessionRequest listener) { - jingleManager.addJingleSessionRequestListener(listener); - } - - /** - * Remove a session request listener. This listener will no longer be notified of new session - * requests. - * @param listener the listener to be added. - */ - public void removeSessionRequestListener(JingleListener.SessionRequest listener) { - jingleManager.removeJingleSessionRequestListener(listener); - } - - /** - * @param comp Comparator to be used when sorting PayloadTypes into order of preference. - */ - public void setPTComparator(Comparator comp) { - ptComparator = comp; - } - - private Class[] getClassArray(Iterator it) { - Set classes = new HashSet(); - while(it.hasNext()) classes.add(it.next().getClass()); - - Class[] result = new Class[classes.size()]; - Iterator itClasses = classes.iterator(); - for(int i = 0; i < result.length; i++) result[i] = (Class) itClasses.next(); - return result; - } - -// Inner classes ------------------------------------------------------------------- - - private class EncodingSupportStore { - - private Set elements = new HashSet(); - - private EncodingSupportElement getElementForPT(PayloadType pt) { - Iterator it = elements.iterator(); - while(it.hasNext()) { - EncodingSupportElement current = (EncodingSupportElement) it.next(); - if(current.getPayloadType().equals(pt)) return current; - } - return null; - } - - public void setEncodingSupport(ContentType ct, PayloadType pt, Class encClass) { - EncodingSupportElement toChange = getElementForPT(pt); - if(toChange == null) { - toChange = new EncodingSupportElement(ct, pt); - toChange.setEncodingClass(encClass); - elements.add(toChange); - } - else toChange.setEncodingClass(encClass); - } - - public void setDecodingSupport(ContentType ct, PayloadType pt, Class decClass) { - EncodingSupportElement toChange = getElementForPT(pt); - if(toChange == null) { - toChange = new EncodingSupportElement(ct, pt); - toChange.setDecodingClass(decClass); - elements.add(toChange); - } - else toChange.setDecodingClass(decClass); - } - - public void remove(PayloadType pt, Class meClass) { - - EncodingSupportElement toRemove = getElementForPT(pt); - if(toRemove.getEncodingClass().equals(meClass)) toRemove.setEncodingClass(null); - if(toRemove.getDecodingClass().equals(meClass)) toRemove.setDecodingClass(null); - if(toRemove.getDecodingClass() == null && toRemove.getEncodingClass() == null) - elements.remove(toRemove); - } - - public Set getSupportedPTsForContentType(ContentType contentType) { - Set result = new HashSet(); - - Iterator it = elements.iterator(); - - while (it.hasNext()) { - EncodingSupportElement current = (EncodingSupportElement) it.next(); - //only reurn PTs that we can encode and decode - if(current.getContentType().equals(contentType) - && current.getEncodingClass() != null - && current.getDecodingClass() != null) - result.add(current.getPayloadType()); - } - - return result; - } - - public Class getEncodingClassForPT(PayloadType pt) { - EncodingSupportElement toReturn = getElementForPT(pt); - if(toReturn == null) return null; - return toReturn.getEncodingClass(); - } - - public Class getDecodingClassForPT(PayloadType pt) { - EncodingSupportElement toReturn = getElementForPT(pt); - if(toReturn == null) return null; - return toReturn.getEncodingClass(); - } - - } - - private class EncodingSupportElement { - - private ContentType contentType; - private PayloadType payloadType; - private Class encodingClass, decodingClass; - - public EncodingSupportElement(ContentType contentType, PayloadType payloadType) { - this.contentType = contentType; - this.payloadType = payloadType; - } - - public Class getDecodingClass() { - return decodingClass; - } - - public void setDecodingClass(Class decodingClass) { - this.decodingClass = decodingClass; - } - - public Class getEncodingClass() { - return encodingClass; - } - - public void setEncodingClass(Class encodingClass) { - this.encodingClass = encodingClass; - } - - public ContentType getContentType() { - return contentType; - } - - public PayloadType getPayloadType() { - return payloadType; - } - } - - private class TransportSupportStore { - private Set elements; - - public void addElement(TransportSupportElement element) { - elements.add(element); - } - - public void remove(Protocol proto, Class mtClass) { - Iterator it = elements.iterator(); - while(it.hasNext()) { - TransportSupportElement current = (TransportSupportElement) it.next(); - if(current.getProtocol().equals(proto) && current.getImplementingClass().equals(mtClass)) - elements.remove(current); - } - } - - public Class getClassForProtocol(TransportCandidate.Protocol protocol) { - Iterator it = elements.iterator(); - while(it.hasNext()) { - TransportSupportElement current = (TransportSupportElement) it.next(); - if(current.getProtocol().equals(protocol)) return current.getImplementingClass(); - } - return null; - } - } - - private class TransportSupportElement { - private TransportCandidate.Protocol protocol; - private Class implementingClass; - - public TransportSupportElement(Protocol protocol, Class implementingClass) { - this.protocol = protocol; - this.implementingClass = implementingClass; - } - - public Class getImplementingClass() { - return implementingClass; - } - - public TransportCandidate.Protocol getProtocol() { - return protocol; - } - - } - - public static class ContentType { - -// Media type constants. Used to differentiate between the different types of connections -// that can be negotiated using Jingle. - - public static final ContentType AUDIO = new ContentType(); - public static final ContentType VIDEO = new ContentType(); - public static final ContentType AUDIO_AND_VIDEO = new ContentType(); - public static final ContentType FILE_SHARING = new ContentType(); - - public boolean equals(Object o) { - return o == this; - } - } - - public static class SessionCreationError extends Error{ - private static final long serialVersionUID = 1L; - public SessionCreationError(String text) { - super(text); - } - } - - //Payload Type comparators------------------------------------------------------------------ - - /** - * PayloadType comparator that orders PayloadTypes by preference level. - */ - public static class DefaultPTC implements Comparator { - - public int compare(Object arg0, Object arg1) { - PayloadType pt0 = (PayloadType) arg0; - PayloadType pt1 = (PayloadType) arg1; - if(FormatTranslator.preferenceLevel(pt0) < FormatTranslator.preferenceLevel(pt1)) return 1; - if(FormatTranslator.preferenceLevel(pt0) > FormatTranslator.preferenceLevel(pt1)) return -1; - else return 0; - } - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaSession.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaSession.java deleted file mode 100644 index f18fab3de..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/JingleMediaSession.java +++ /dev/null @@ -1,248 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.InputStream; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import javax.sound.sampled.AudioInputStream; - -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smackx.jingle.JingleListener; -import org.jivesoftware.smackx.jingle.JingleSession; -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaListener.Output; -import org.jivesoftware.smackx.jingle.media.MediaEngine.UnableToConfigureMediaEngine; -import org.jivesoftware.smackx.nat.TransportCandidate; - -/** - * Class representing ongoing peer-to-peer connections negotiated via Jingle. - * - * @author Alasdair North - * - */ -public class JingleMediaSession implements JingleListener.Session { - - private JingleSession jingleSession; - private AudioInputStream input; - private JingleMediaManager mediaManager; - private Set outputListeners; - - private MediaEngine.Encoding encodingMediaEngine; - private MediaEngine.Decoding decodingMediaEngine; - private MediaTransport mediaTransport; - - /** - * Create a new JingleMediaSession from the given JingleSession. - * @param input the DataSource from which data will be taken. - * @param jingleSession the JingleSession object used to negotiate session parameters. - * @param mediaManager the JingleMediaManager that created this JingleMediaSession. - */ - public JingleMediaSession(AudioInputStream input, JingleSession jingleSession, JingleMediaManager mediaManager) { - this.input = input; - this.jingleSession = jingleSession; - this.mediaManager = mediaManager; - - outputListeners = new HashSet(); - - jingleSession.addListener(this); - } - - /** - * This method will return null until data starts being received. - * @return data received and decoded by the JingleMediaSession. - */ - public InputStream getOutput() { - if(decodingMediaEngine == null) return null; - return decodingMediaEngine.getOutput(); - } - - /** - * Release all resources held by the JingleMediaSession and cease operation. - */ - public void close() { - jingleSession.close(); - jingleSession = null; - encodingMediaEngine.close(); - encodingMediaEngine = null; - decodingMediaEngine.close(); - decodingMediaEngine = null; - mediaTransport.close(); - mediaTransport = null; - } - - private void notifyOutputListeners(InputStream output) { - Iterator it = outputListeners.iterator(); - while(it.hasNext()) ((JingleMediaListener.Output) it.next()).outputChanged(output); - } - - /** - * Add an output listener to be notified when the JingleMediaSessions output changes. - * @param listener the listener to be added. - */ - public void addOutputListener(Output listener) { - outputListeners.add(listener); - } - - /** - * Remove an output listener. This listener will no longer be notified when the - * JingleMediaSessions output changes. - * @param listener the listner to be removed. - */ - public void removeOutputListener(Output listener) { - outputListeners.remove(listener); - } - - /** - * Add a JingleListener to be notified of JingleSession events. - * @param listener the listener to be added. - */ - public void addJingleListener(JingleListener listener) { - if(listener instanceof Session) jingleSession.addListener(listener); - if(listener instanceof Media) jingleSession.addMediaListener((Media)listener); - if(listener instanceof Transport) - jingleSession.addTransportListener((Transport)listener); - } - - /** - * Remove a JingleListener. This listener will no longer be notified of JingleSession events. - * @param listener the listner to be removed. - */ - public void removeJingleListener(JingleListener listener) { - if(listener instanceof Session) jingleSession.removeListener(listener); - if(listener instanceof Media) jingleSession.removeMediaListener((Media)listener); - if(listener instanceof Transport) - jingleSession.removeTransportListener((Transport)listener); - } - -// JingleListener.Session methods -------------------------------------------------------- - - public void sessionEstablished() { - // TODO Should anything be done here? - } - - public void sessionDeclined() { - // TODO Should anything be done here? - } - - public void sessionRedirected(String redirection) { - // TODO Start a new JingleMediaSession? - } - - public void sessionClosed() { - close(); - } - - public void sessionClosedOnError(Exception e) { - close(); - } - - public void sessionDeclined(String reason) { - // TODO Auto-generated method stub - - } - - public void sessionClosed(String reason) { - // TODO Auto-generated method stub - - } - - public void sessionClosedOnError(XMPPException e) { - // TODO Auto-generated method stub - - } - - public void sessionEstablished(final PayloadType pt, final TransportCandidate rc, final TransportCandidate lc) { - - Thread mediaConnectionCreationThread = new Thread() { - public void run() { - - encodingMediaEngine = mediaManager.getEncodingMediaEngine(pt, input); - encodingMediaEngine.addOutputListener(new EncOutListener()); - try { - encodingMediaEngine.configure(); - } catch (UnableToConfigureMediaEngine e1) { - e1.printStackTrace(); - } - - //wait for the encoding engine to configure itself - while(encodingMediaEngine.getState() != MediaEngine.CONFIGURED) { - try { - wait(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - encodingMediaEngine.start(); - - mediaTransport = mediaManager.getMediaTransport(rc, lc); - mediaTransport.addOutputListener(new TranOutListener()); - - mediaTransport.setInput(encodingMediaEngine.getOutput()); - mediaTransport.configure(); - -// wait for the transport to configure itself - while(mediaTransport.getTransmitterState() != MediaTransport.TRANSMITTER_CONFIGURED || - mediaTransport.getReceiverState() != MediaTransport.RECEIVER_CONFIGURED) { - try { - wait(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - mediaTransport.start(); - } - }; - - mediaConnectionCreationThread.start(); - - } - - private class EncOutListener implements JingleMediaListener.Output { - - public void outputChanged(InputStream output) { - - - } - - } - - private class TranOutListener implements JingleMediaListener.Output { - - public void outputChanged(InputStream output) { - -// hook it up to a decoding media engine - decodingMediaEngine = mediaManager.getDecodingMediaEngine(encodingMediaEngine.getPayloadType(), output); - decodingMediaEngine.addOutputListener(new DecOutListener()); - - try { - decodingMediaEngine.configure(); - } catch (UnableToConfigureMediaEngine e1) { - e1.printStackTrace(); - } - - while(decodingMediaEngine.getState() != MediaEngine.CONFIGURED) { - try { - wait(100); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - decodingMediaEngine.start(); - } - - } - - private class DecOutListener implements JingleMediaListener.Output { - - public void outputChanged(InputStream output) { - notifyOutputListeners(output); - } - - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaEngine.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaEngine.java deleted file mode 100644 index 89bdf60e8..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaEngine.java +++ /dev/null @@ -1,287 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.jingle.media.JingleMediaManager.ContentType; - -/** - * MediaEngines encode and decode data. - * - * @author Alasdair North - */ -public abstract class MediaEngine { - - public static final int INSTANTIATED = 0; - public static final int CONFIGURING = 1; - public static final int CONFIGURED = 2; - public static final int STARTED = 3; - public static final int CLOSED = 4; - - private static final OutputMonitoringThread monitorThread = new OutputMonitoringThread(); - - private PayloadType encodingFormat; - private Set outputListeners; - - - /** - * This empty constructor is needed by the SPI, it doesn't do anything other than create an - * object. - */ - public MediaEngine() {} - - /** - * Create a new MediaEngine. - * @param encodedFormat The Format that encoded data dealt with by this MediaEngine is in. - */ - public MediaEngine(PayloadType encodedFormat) { - this.encodingFormat = encodedFormat; - outputListeners = new HashSet(); - } - - /** - * @return The InputStream from which this MediaEngine gets its data. - */ - public abstract InputStream getInput(); - - /** - * Set the MediaEngine's input, this should be done before configuring the MediaEngine or - * calling one of the getSupportedPayloadTypes methods. - * @param input Set the DataSource from which this MediaEngine gets its data. - */ - public abstract void setInput(InputStream input); - - /** - * This method does not need to return anything other than null until the MediaEngine is - * STARTED. When it changes output listeners will be notified of the new output DataSource. - * @return the DataSource representing the output of this MediaEngine. - */ - public abstract InputStream getOutput(); - - /** - * @return the PayloadType of encoded data. - */ - public synchronized PayloadType getPayloadType() { - return encodingFormat; - } - - /** - * Get the current state of the MediaEngine. This will be one of the constants specified in - * MediaEngine. - * @return the MediaEngine's current state. - */ - public abstract int getState(); - - /** - * Called to intitiate the transition from the INSTANTIATED state to the CONFIGURING state, and - * then finally to CONFIGURED. - * @throws UnableToConfigureMediaEngine when unable to configure. - */ - public abstract void configure() throws UnableToConfigureMediaEngine; - - /** - * Starts the transition from CONFIGURED to STARTED. When this is called the MediaEngine - * should start to process data and output it. - */ - public abstract void start(); - - /** - * Starts the transition from STARTED back to CONFIGURED. When this is called the MediaEngine - * should stop sending data to the output. - */ - public abstract void stop(); - - /** - * Releases all the resources held by the MediaEngine and ceases it's activity. This will put - * it back to the INSTANTIATED state. In order to be used again it will have to be configured - * again. - */ - public abstract void close(); - - public abstract Set getSupportedPayloadTypes(ContentType contentType); - - /** - * Add an output listener to the MediaEngine. This listener will be notified when the output - * changes to anything other than null. - * @param listener the listener to be added. - */ - public void addOutputListener(JingleMediaListener.Output listener) { - outputListeners.add(listener); - if(!monitorThread.isStarted()) monitorThread.setStarted(true); - if(!monitorThread.isInMonitoredList(this)) monitorThread.addToMonitoredList(this); - } - - /** - * Remove an output listener from the MediaEngine. This listener will no longer receive - * notifications of changes in output. - * @param listener the listener to be removed. - */ - public void removeOutputListener(JingleMediaListener.Output listener) { - outputListeners.remove(listener); - if(outputListeners.isEmpty()) monitorThread.removeFromMonitoredList(this); - if(monitorThread.isMonitoredEmpty()) monitorThread.setStarted(false); - } - - private void notifyOutputListenersOutputReady(InputStream output) { - Iterator it = outputListeners.iterator(); - while(it.hasNext()) ((JingleMediaListener.Output) it.next()).outputChanged(output); - } - - /** - * Subclasses of MediaEngine.Encoding are responsible for encoding raw data to be transmitted - * by MediaTransport classes. In order to be used by the jingle media code they must have - * entries in the META-INF/services directory of a jar file in the class path. They must also - * have a zero argument constructor. - * - * @author Alasdair North - */ - public static abstract class Encoding extends MediaEngine { - - public Encoding(PayloadType outputFormat) { - super(outputFormat); - } - - /** - * Return a set of the PayloadTypes that this class can encode data to for the given ContentType. - * These ContentTypes are specified using the constants in JingleMediaManager. The MediaEngine's - * input must be specified before calling this method. - * @param contentType - * @return Set of supported PayloadTypes - */ - public abstract Set getSupportedPayloadTypes(ContentType contentType); - } - - /** - * Subclasses of MediaEngine.Decoding are responsible for decoding encoded data received - * by MediaTransport classes. In order to be used by the jingle media code they must have - * entries in the META-INF/services directory of a jar file in the class path. They must also - * have a zero argument constructor. - * - * @author Alasdair North - */ - public static abstract class Decoding extends MediaEngine { - - public Decoding(PayloadType inputFormat) { - super(inputFormat); - } - - /** - * Return a set of the PayloadTypes that this class can decode data from for the given ContentType. - * These ContentTypes are specified using the constants in JingleMediaManager. The MediaEngine's - * input does not need to be specified before calling this method. - * @param contentType - * @return Set of supported PayloadTypes - */ - public abstract Set getSupportedPayloadTypes(ContentType contentType); - } - - public static class StateOrderViolationError extends Error { - private static final long serialVersionUID = 1L; - - public StateOrderViolationError(String text) { - super(text); - } - - } - - public static class InputNotSetError extends Error { - private static final long serialVersionUID = 1L; - - public InputNotSetError(String text) { - super(text); - } - } - - public static class UnableToConfigureMediaEngine extends Exception { - private static final long serialVersionUID = 1L; - - public UnableToConfigureMediaEngine(Throwable cause) { - super(cause); - } - - public UnableToConfigureMediaEngine(String cause) { - super(cause); - } - } - - /** - * A thread to monitor the outputs of MediaEngines and notify output listeners of changes. - * @author Alasdair North - */ - private static class OutputMonitoringThread extends Thread { - - private volatile boolean started = false; -// Map from MediaEngines to DataSources used to monitor for changes in output - private volatile Map monitored = new HashMap(); - - public boolean isStarted() { - return started; - } - - public void setStarted(boolean started) { - this.started = started; - if(started) super.start(); - } - - public void addToMonitoredList(MediaEngine me) { - synchronized(monitored) { - monitored.put(me, null); - } - } - - public void removeFromMonitoredList(MediaEngine me) { - synchronized(monitored) { - monitored.remove(me); - } - } - - public boolean isInMonitoredList(MediaEngine me) { - synchronized(monitored) { - return monitored.containsKey(me); - } - } - - public boolean isMonitoredEmpty() { - synchronized(monitored) { - return monitored.isEmpty(); - } - } - - public void run() { - - while(started) { - synchronized(monitored) { - Set keySet = new HashSet(monitored.keySet()); - Iterator it = keySet.iterator(); - while(it.hasNext()) { - - MediaEngine currentKey = (MediaEngine) it.next(); - InputStream keysOutput; - try { - keysOutput = currentKey.getOutput(); - } catch (Exception e) { - keysOutput = null; - } - -// should listener be changed to notify of changes in output and notify of null -// as well? - if(keysOutput != monitored.get(currentKey) && keysOutput != null) - currentKey.notifyOutputListenersOutputReady(keysOutput); - - monitored.put(currentKey, keysOutput); - } - } - } - try { - Thread.sleep(2000); - } catch (InterruptedException e) {} - } - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaTransport.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaTransport.java deleted file mode 100644 index 14407faae..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/MediaTransport.java +++ /dev/null @@ -1,172 +0,0 @@ -package org.jivesoftware.smackx.jingle.media; - -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; - -import java.io.InputStream; - -import org.jivesoftware.smackx.nat.TransportCandidate; - -/** - * Subclasses of MediaTransport are responisble for the transmission of data, implementing - * TransportCandidates negotiated by the TransportNegotiator. - * - * @author Alasdair North - * - */ -public abstract class MediaTransport { - - public static final int TRANSMITTER_INSTANTIATED = 0; - public static final int TRANSMITTER_CONFIGURED = 1; - public static final int TRANSMITTER_SENDING = 2; - public static final int TRANSMITTER_CLOSED = 3; - - - public static final int RECEIVER_INSTANTIATED = 7; - public static final int RECEIVER_CONFIGURED = 8; - public static final int RECEIVER_WAITING = 9; - public static final int RECEIVER_RECEIVING = 10; - public static final int RECEIVER_CLOSED = 11; - - private TransportCandidate remoteCandidate, localCandidate; - private Set outputListeners; - - /** - * This empty constructor is needed by the SPI, it shouldn't do anything other than create an - * object. - */ - public MediaTransport(){} - - /** - * Create a new MediaTransport to use the transport method specified by the successful - * TransportCandidate. - * @param remoteCandidate The remote candidate to use for connecting to the remote service. - * @param localCandidate The local candidate where we must listen for connections - */ - public MediaTransport(TransportCandidate remoteCandidate, TransportCandidate localCandidate) { - this.localCandidate = localCandidate; - this.remoteCandidate = remoteCandidate; - outputListeners = new HashSet(); - } - - /** - * Called to initiate the transition from the INSTANTIATED states to CONFIGURED states. - */ - public abstract void configure(); - - /** - * Initiates transition from TRANSMITTER_CONFIGURED to TRANSMITTER_SENDING and - * RECEIVER_CONFIGURED to RECEIVER_WAITING. The MediaTransport will start transmitting data - * from the input and will begin waiting for data transmitted from the other end. - */ - public abstract void start(); - - /** - * Initiates transition from TRANSMITTER_SENDING to TRANSMITTER_CONFIGURED and - * RECEIVER_WAITING to RECEIVER_CONFIGURED. The transmitter stops transmitting and the - * receiver stops receiving and also stops listening for data transmitted from the other end. - */ - public abstract void stop(); - - /** - * Releases all resources held by the MediaTransport and cease's its activity. Will return it - * to the INSTANTIATED states (i.e. it must be reconfigured before being used again). - */ - public abstract void close(); - - /** - * @return the state of the transmission side of the MediaTransport. - */ - public abstract int getTransmitterState(); - - /** - * @return the state of the receiving side of the MediaTransport. - */ - public abstract int getReceiverState(); - - /** - * @return a Set of the TransportCandidate.Protocols supported by this MediaTransport. - */ - public abstract Set getSupportedProtocols(); - - public TransportCandidate getLocalCandidate() { - return localCandidate; - } - - public TransportCandidate getRemoteCandidate() { - return remoteCandidate; - } - - /** - * @return the DataSource from which this MediaTransport gets its data. - */ - public abstract InputStream getInput(); - - /** - * This method must be called before the MediaTransport is started. - * @param input the DataSource from which this MediaTransport will get its data. - */ - public abstract void setInput(InputStream input); - - /** - * This method may return nothing but null until the MediaTransport is in the RECEIVER_RECEIVING - * state. - * @return the data received bt the MediaTransport. - */ - public abstract InputStream getOutput(); - - /** - * Add an output listener to the MediaTransport. This listener will be notified when the - * MediaTransport receives a new data stream. - * @param listener the listener to be added. - */ - public void addOutputListener(JingleMediaListener.Output listener) { - outputListeners.add(listener); - } - - /** - * Add an output listener to the MediaTransport. This listener will no longer be notified - * of new received data streams. - * @param listener the listener to be removed. - */ - public void removeOutputListener(JingleMediaListener.Output listener) { - outputListeners.remove(listener); - } - - /** - * Notify the output listeners that a new output is available. - * @param output new output DataSource. - */ - protected void notifyOutputListenersOutputReady(InputStream output) { - Iterator it = outputListeners.iterator(); - while(it.hasNext()) ((JingleMediaListener.Output) it.next()).outputChanged(output); - } - - /** - * @param tc - * @return the Protocol to be used for implementing the given TransportCandidate. - */ - public static TransportCandidate.Protocol getProtocol(TransportCandidate tc) { - if(tc instanceof TransportCandidate.Ice) return ((TransportCandidate.Ice) tc).getProto(); - else return TransportCandidate.Protocol.UDP; - } - - public static class UnableToConfigure extends Error { - private static final long serialVersionUID = 1L; - public UnableToConfigure(Throwable cause) { - super(cause); - } - public UnableToConfigure(String cause) { - super(cause); - } - } - - public static class UnableToStart extends Error { - private static final long serialVersionUID = 1L; - public UnableToStart(Throwable cause) { - super(cause); - } - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISDataSource.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISDataSource.java deleted file mode 100644 index 62608fb8b..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISDataSource.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.io.IOException; - -import javax.media.Time; -import javax.media.protocol.PushBufferDataSource; -import javax.media.protocol.PushBufferStream; -import javax.sound.sampled.AudioInputStream; - -public class AISDataSource extends PushBufferDataSource { - - private AISPushBufferStream[] streams = new AISPushBufferStream[1]; - private boolean connected = false; - private boolean started = false; - - public AISDataSource(AudioInputStream ais) { - streams[0] = new AISPushBufferStream(ais); - } - - public PushBufferStream[] getStreams() { - return streams; - } - - public String getContentType() { - if(!connected) { - System.err.println("Error: DataSource not connected"); - return null; - } - return "raw"; - } - - public void connect() throws IOException { - connected = true; - } - - public void disconnect() { - try { - if(started) stop(); - } catch (IOException e) {} - connected = false; - } - - public void start() throws IOException { - if(!connected) throw new Error("DataSource must be connected before it can be started"); - if(!started) { - started = true; - streams[0].start(true); - } - - } - - public void stop() throws IOException { - if(connected && started) { - started = false; - streams[0].start(false); - } - } - - public Object getControl(String arg0) { - return null; - } - - public Object[] getControls() { - return null; - } - - public Time getDuration() { - return DURATION_UNKNOWN; - } - -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISPushBufferStream.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISPushBufferStream.java deleted file mode 100644 index 6b3012d76..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/AISPushBufferStream.java +++ /dev/null @@ -1,127 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.io.IOException; - -import javax.media.Buffer; -import javax.media.Format; -import javax.media.protocol.BufferTransferHandler; -import javax.media.protocol.ContentDescriptor; -import javax.media.protocol.PushBufferStream; -import javax.sound.sampled.AudioInputStream; - - -public class AISPushBufferStream implements PushBufferStream, Runnable { - - private Format format; - private AudioInputStream data; - private ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW); - - private BufferTransferHandler transferHandler; - private int seqNo; - - private Thread thread; - private boolean threadStarted; - - public AISPushBufferStream(AudioInputStream ais) { - data = ais; - format = FormatTranslator.toJMFFormat(ais.getFormat()); - thread = new Thread(this); - seqNo = 0; - } - - public Format getFormat() { - return format; - } - - public synchronized void read(Buffer buff) throws IOException { - - - int dataAvailable = 0; - try { - dataAvailable = data.available(); - } catch (IOException e) { - e.printStackTrace(); - } - - if(dataAvailable > 0) { - byte[] outdata = new byte[dataAvailable]; - int dataRead = data.read(outdata); - - buff.setFormat(getFormat()); - buff.setData(outdata); - - buff.setLength(dataRead); - buff.setSequenceNumber(seqNo); - buff.setHeader(null); - buff.setFlags(0); - } - - - } - - public synchronized void setTransferHandler(BufferTransferHandler transferHandler) { - this.transferHandler = transferHandler; - notifyAll(); - } - - public ContentDescriptor getContentDescriptor() { - return cd; - } - - public long getContentLength() { - return LENGTH_UNKNOWN; - } - - public boolean endOfStream() { - return false; - } - - public Object[] getControls() { - return null; - } - - public Object getControl(String arg0) { - //no controls - return null; - } - - public synchronized void start(boolean started) { - threadStarted = started; - if(started && !thread.isAlive()) { - thread = new Thread(this); - thread.start(); - } - notifyAll(); - } - - public void run() { - while(threadStarted) { - synchronized(this) { - while(transferHandler == null && threadStarted) { - try { - wait(1000); - } catch(InterruptedException e) {} - } - } - - int dataAvailable = 0; - try { - dataAvailable = data.available(); - } catch (IOException e) { - e.printStackTrace(); - } - - //loop until there is some data to be read - if(threadStarted && transferHandler != null) { - if(dataAvailable > 0) { - transferHandler.transferData(this); - } - else try { - Thread.sleep(10); - } catch (InterruptedException e) {} - } - } - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DSInputStream.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DSInputStream.java deleted file mode 100644 index c8be4af11..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DSInputStream.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.io.IOException; -import java.io.InputStream; - -import javax.media.Buffer; -import javax.media.protocol.BufferTransferHandler; -import javax.media.protocol.PushBufferDataSource; -import javax.media.protocol.PushBufferStream; - -public class DSInputStream extends InputStream implements BufferTransferHandler { - - private byte[] circularByteBuffer; - private int dataStart; - private int dataEnd; - - private PushBufferDataSource input; - - public DSInputStream (PushBufferDataSource input, int bufferSize) { - input.getStreams()[0].setTransferHandler(this); - this.input = input; - dataStart = 0; - dataEnd = 0; - circularByteBuffer = new byte[bufferSize]; - } - - public int read() throws IOException { - while(true) { - if(dataStart == dataEnd) { - try { - Thread.sleep(10); - } catch (InterruptedException e) {} - } - else synchronized(circularByteBuffer) { - int returnValue = circularByteBuffer[dataStart]; - if(dataStart == circularByteBuffer.length - 1) dataStart = 0; - else dataStart ++; - return returnValue; - } - } - } - - public int available() { - synchronized(circularByteBuffer) { - if(dataStart <= dataEnd) return dataEnd - dataStart; - else return dataEnd - dataStart + circularByteBuffer.length + 1; - } - } - - private void addData(byte[] data, int offset, int length) { - if(data.length > 0 && offset + length <= data.length && offset >= 0 && length > 0) { - synchronized(circularByteBuffer) { - for(int i = offset; i < offset + length; i++) { - if(dataEnd == circularByteBuffer.length - 1) { -// wrap around - circularByteBuffer[0] = data[i]; - dataEnd = 0; - } else { - circularByteBuffer[dataEnd + 1] = data[i]; - dataEnd++; - } - -// if data has been overwritten then move on the start marker - if(dataStart == dataEnd) dataStart++; - if(dataStart == circularByteBuffer.length) dataStart = 0; - } - } - } - } - - public int read(byte[] b, int off, int len) { - if(b == null) throw new NullPointerException(); - if(off < 0 || len < 0 || off + len > b.length) throw new IndexOutOfBoundsException(); - if(len > 0) { - synchronized(circularByteBuffer) { - int bytesRead = 0; - - for(int i = off; i < off+len; i++) { - if(dataStart == dataEnd) break; - b[i] = circularByteBuffer[dataStart]; - bytesRead++; - if(dataStart == circularByteBuffer.length - 1) dataStart = 0; - else dataStart ++; - } - return bytesRead; - } - } - return 0; - } - - public int read(byte[] b) { - return read(b, 0, b.length); - } - - public void close() { - synchronized(circularByteBuffer) { - circularByteBuffer = null; - input.getStreams()[0].setTransferHandler(null); - } - } - - public void transferData(PushBufferStream pbs) { - Buffer buff = new Buffer(); - try { - pbs.read(buff); - byte[] data = (byte[]) buff.getData(); - addData(data, buff.getOffset(), buff.getLength()); - } catch (IOException e) { - e.printStackTrace(); - } - - } - - public boolean markSupported() { - return false; - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DefaultFormatTranslationProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DefaultFormatTranslationProvider.java deleted file mode 100644 index ac5d5367c..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/DefaultFormatTranslationProvider.java +++ /dev/null @@ -1,268 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import javax.media.Format; -import javax.media.format.AudioFormat; - -import org.jivesoftware.smackx.jingle.PayloadType; - -public class DefaultFormatTranslationProvider implements FormatTranslationProvider { - - private static final AudioFormat JMF_STATIC_PT_0 = new AudioFormat(AudioFormat.ULAW_RTP, 8000.0, 8, 1, - AudioFormat.LITTLE_ENDIAN, AudioFormat.NOT_SPECIFIED, 8, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_3 = new AudioFormat(AudioFormat.GSM_RTP, 8000.0, AudioFormat.NOT_SPECIFIED, - 1, AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, 264, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_4 = new AudioFormat(AudioFormat.G723_RTP, 8000.0, AudioFormat.NOT_SPECIFIED, - 1, AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, 192, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_5 = new AudioFormat(AudioFormat.DVI_RTP, 8000.0, 4, 1); - - private static final AudioFormat JMF_STATIC_PT_6 = new AudioFormat(AudioFormat.DVI_RTP, 16000.0, 4, 1); - - private static final AudioFormat JMF_STATIC_PT_8 = new AudioFormat(AudioFormat.ALAW, 8000.0, 8, 1, - AudioFormat.LITTLE_ENDIAN, AudioFormat.NOT_SPECIFIED, 8, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_10 = new AudioFormat(AudioFormat.LINEAR, 44100.0, 16, 2, - AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_11 = new AudioFormat(AudioFormat.LINEAR, 44100.0, 16, 1, - AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - private static final AudioFormat JMF_STATIC_PT_14 = new AudioFormat(AudioFormat.MPEG_RTP, 44100.0, 16, 1); - - private static final AudioFormat JMF_STATIC_PT_16 = new AudioFormat(AudioFormat.DVI_RTP, 11025.0, 4, 1); - - private static final AudioFormat JMF_STATIC_PT_17 = new AudioFormat(AudioFormat.DVI_RTP, 22050.0, 4, 1); - - - private static final javax.sound.sampled.AudioFormat JS_STATIC_PT_0 = new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.ULAW, 8000f, 8, 1, 1, 8000f, false); - - private static final javax.sound.sampled.AudioFormat JS_STATIC_PT_8 = new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.ALAW, 8000f, 8, 1, 1, 8000f, false); - - private static final javax.sound.sampled.AudioFormat JS_STATIC_PT_10 = new javax.sound.sampled.AudioFormat(44100f, 16, 2, true, true); - - private static final javax.sound.sampled.AudioFormat JS_STATIC_PT_11 = new javax.sound.sampled.AudioFormat(44100f, 16, 1, true, true); - - - public Object translate(Object sourceFormat, Class targetClass) { - if(targetClass == AudioFormat.class || targetClass == Format.class) { - if(sourceFormat instanceof PayloadType) return toJMFAudioFormat((PayloadType) sourceFormat); - else if(sourceFormat instanceof javax.sound.sampled.AudioFormat) return toJMFAudioFormat((javax.sound.sampled.AudioFormat) sourceFormat); - else if(sourceFormat instanceof AudioFormat) return sourceFormat; - - } else if(targetClass == javax.sound.sampled.AudioFormat.class) { - if(sourceFormat instanceof PayloadType) return toJSAudioFormat((PayloadType) sourceFormat); - else if(sourceFormat instanceof AudioFormat) return toJSAudioFormat((AudioFormat) sourceFormat); - else if(sourceFormat instanceof javax.sound.sampled.AudioFormat) return sourceFormat; - - } else if(targetClass == PayloadType.class || targetClass == PayloadType.Audio.class) { - if(sourceFormat instanceof javax.sound.sampled.AudioFormat) return toPayloadType((javax.sound.sampled.AudioFormat) sourceFormat); - else if(sourceFormat instanceof AudioFormat) return toPayloadType((AudioFormat) sourceFormat); - else if(sourceFormat instanceof PayloadType) return sourceFormat; - } - - return null; - } - - private AudioFormat toJMFAudioFormat(PayloadType pt) { - AudioFormat result = null; - - //first the static payload types - switch(pt.getId()) { - case 0: result = JMF_STATIC_PT_0; break; - case 3: result = JMF_STATIC_PT_3; break; - case 4: result = JMF_STATIC_PT_4; break; - case 5: result = JMF_STATIC_PT_5; break; - case 6: result = JMF_STATIC_PT_6; break; - case 8: result = JMF_STATIC_PT_8; break; - case 10: result = JMF_STATIC_PT_10; break; - case 11: result = JMF_STATIC_PT_11; break; - case 14: result = JMF_STATIC_PT_14; break; - case 16: result = JMF_STATIC_PT_16; break; - case 17: result = JMF_STATIC_PT_17; break; - } - - //then the dynamic ones - if(result == null) { - if(!(pt instanceof PayloadType.Audio)) throw new Error("PayloadType had dynamic ID but was" + - " not an instance of PayloadType.Audio and so did not contain enough" + - " information."); - PayloadType.Audio pta = (PayloadType.Audio) pt; - - if(pta.getClockRate() == 0) throw new Error("Sampling rate was" + - " not set in the given PayloadType."); - if(pta.getName() == null) throw new Error("Codec name was" + - " not set in the given PayloadType"); - - if(pta.getName().equals("PCMA")) { - result = new AudioFormat(AudioFormat.ALAW, pta.getClockRate(), 8, pta.getChannels(), - AudioFormat.LITTLE_ENDIAN, AudioFormat.NOT_SPECIFIED, 8, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("PCMU")) { - result = new AudioFormat(AudioFormat.ULAW_RTP, pta.getClockRate(), 8, pta.getChannels(), - AudioFormat.LITTLE_ENDIAN, AudioFormat.NOT_SPECIFIED, 8, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("L16")) { - result = new AudioFormat(AudioFormat.LINEAR, pta.getClockRate(), 16, pta.getChannels(), - AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("L8")) { - result = new AudioFormat(AudioFormat.LINEAR, pta.getClockRate(), 8, pta.getChannels(), - AudioFormat.BIG_ENDIAN, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("MPA")) { - result = new AudioFormat(AudioFormat.MPEG_RTP, pta.getClockRate(), 16, pta.getChannels()); - - } else if(pta.getName().equals("GSM")) { - result = new AudioFormat(AudioFormat.GSM_RTP, pta.getClockRate(), AudioFormat.NOT_SPECIFIED, - pta.getChannels(), AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, 264, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("G723")) { - result = new AudioFormat(AudioFormat.G723_RTP, pta.getClockRate(), AudioFormat.NOT_SPECIFIED, - pta.getChannels(), AudioFormat.NOT_SPECIFIED, AudioFormat.NOT_SPECIFIED, 192, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(pta.getName().equals("DVI4")) { - result = new AudioFormat(AudioFormat.DVI_RTP, pta.getClockRate(), 4, pta.getChannels()); - } - } - - return result; - } - - private AudioFormat toJMFAudioFormat(javax.sound.sampled.AudioFormat af) { - - if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED)) { - int endianness = af.isBigEndian() ? AudioFormat.BIG_ENDIAN : AudioFormat.LITTLE_ENDIAN; - - return new AudioFormat(AudioFormat.LINEAR, af.getSampleRate(), af.getSampleSizeInBits(), af.getChannels(), - endianness, AudioFormat.SIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.PCM_UNSIGNED)) { - int endianness = af.isBigEndian() ? AudioFormat.BIG_ENDIAN : AudioFormat.LITTLE_ENDIAN; - - return new AudioFormat(AudioFormat.LINEAR, af.getSampleRate(), af.getSampleSizeInBits(), af.getChannels(), - endianness, AudioFormat.UNSIGNED, AudioFormat.NOT_SPECIFIED, - AudioFormat.NOT_SPECIFIED, byte[].class); - - } else { - PayloadType pt = toPayloadType(af); - if(pt != null) return toJMFAudioFormat(pt); - return null; - } - } - - private javax.sound.sampled.AudioFormat toJSAudioFormat(PayloadType pt) { - //Static payload types - switch(pt.getId()) { - case 0: return JS_STATIC_PT_0; - case 8: return JS_STATIC_PT_8; - case 10: return JS_STATIC_PT_10; - case 11: return JS_STATIC_PT_11; - } - - //Dynamic payload types - if(pt instanceof PayloadType.Audio) { - PayloadType.Audio pta = (PayloadType.Audio) pt; - if(pta.getName() != null && pta.getChannels() != 0 && pta.getClockRate() != 0f) { - if(pta.getName().equals("PCMU")) { - return new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.ULAW, pta.getClockRate(), 8, pta.getChannels(), pta.getChannels(), pta.getClockRate(), false); - } else if(pta.getName().equals("PCMA")) { - return new javax.sound.sampled.AudioFormat(javax.sound.sampled.AudioFormat.Encoding.ALAW, pta.getClockRate(), 8, pta.getChannels(), pta.getChannels(), pta.getClockRate(), false); - } else if(pta.getName().equals("L16")) { - return new javax.sound.sampled.AudioFormat(pta.getClockRate(), 16, pta.getChannels(), true, true); - } else if(pta.getName().equals("L8")) { - return new javax.sound.sampled.AudioFormat(pta.getClockRate(), 8, pta.getChannels(), true, true); - } - } - } - - return null; - } - - private javax.sound.sampled.AudioFormat toJSAudioFormat(AudioFormat af) { - if(af.getEncoding().equals(AudioFormat.LINEAR)) { - return new javax.sound.sampled.AudioFormat((float) af.getSampleRate(), af.getSampleSizeInBits(), af.getChannels(), - af.getSigned() == AudioFormat.SIGNED, af.getEndian() == AudioFormat.BIG_ENDIAN); - } else { - PayloadType pt = toPayloadType(af); - if(pt != null) return toJSAudioFormat(pt); - return null; - } - } - - private PayloadType toPayloadType(AudioFormat af) { - - //static payload types - if((FormatTranslator.equals(af, JMF_STATIC_PT_0))) return new PayloadType(0, "PCMU"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_3))) return new PayloadType(3, "GSM"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_4))) return new PayloadType(4, "G723"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_5))) return new PayloadType(5, "DVI4"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_6))) return new PayloadType(6, "DVI4"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_8))) return new PayloadType(8, "PCMA"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_10))) return new PayloadType(10, "L16"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_11))) return new PayloadType(11, "L16"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_14))) return new PayloadType(14, "MPA"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_16))) return new PayloadType(16, "DVI4"); - if((FormatTranslator.equals(af, JMF_STATIC_PT_17))) return new PayloadType(17, "DVI4"); - - //dynamic payload types - String name = ""; - if(af.getEncoding().equals(AudioFormat.ALAW) && af.getSampleSizeInBits() == 8) name = "PCMA"; - else if(af.getEncoding().equals(AudioFormat.GSM_RTP) && af.getFrameSizeInBits() == 264) name = "GSM"; - else if(af.getEncoding().equals(AudioFormat.G723_RTP) && af.getFrameSizeInBits() == 192) name = "G723"; - else if((af.getEncoding().equals(AudioFormat.DVI) || af.getEncoding().equals(AudioFormat.DVI_RTP)) && af.getSampleSizeInBits() == 4) name = "DVI4"; - else if((af.getEncoding().equals(AudioFormat.ULAW) || af.getEncoding().equals(AudioFormat.ULAW_RTP)) && af.getSampleSizeInBits() == 8) name = "PCMU"; - else if(af.getEncoding().equals(AudioFormat.LINEAR) && af.getSampleSizeInBits() == 16 && af.getEndian() == AudioFormat.BIG_ENDIAN && af.getSigned() == AudioFormat.SIGNED) name = "L16"; - else if(af.getEncoding().equals(AudioFormat.LINEAR) && af.getSampleSizeInBits() == 8 && af.getEndian() == AudioFormat.BIG_ENDIAN && af.getSigned() == AudioFormat.SIGNED) name = "L8"; - else if((af.getEncoding().equals(AudioFormat.MPEG) || af.getEncoding().equals(AudioFormat.MPEG_RTP)) && af.getSampleSizeInBits() == 16) name = "MPA"; - - if(name != "") { - int id = PTIDAssigner.getDynamicID(name, af.getChannels(), (float) af.getSampleRate()); - return new PayloadType.Audio(id, name, af.getChannels(), (int) Math.round(af.getSampleRate())); - } - - return null; - } - - private PayloadType toPayloadType(javax.sound.sampled.AudioFormat af) { -// Static payload types - if(FormatTranslator.equals(af, JS_STATIC_PT_0)) return new PayloadType(0, "PCMU"); - if(FormatTranslator.equals(af, JS_STATIC_PT_8)) return new PayloadType(8, "PCMA"); - if(FormatTranslator.equals(af, JS_STATIC_PT_10)) return new PayloadType(10, "L16"); - if(FormatTranslator.equals(af, JS_STATIC_PT_11)) return new PayloadType(11, "L16"); - - //Dynamic payload types - String name = ""; - if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.ULAW) && af.getSampleSizeInBits() == 8) name = "PCMU"; - else if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.ALAW) && af.getSampleSizeInBits() == 8) name = "PCMA"; - else if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED) && af.getSampleSizeInBits() == 16 && af.isBigEndian()) name = "L16"; - else if(af.getEncoding().equals(javax.sound.sampled.AudioFormat.Encoding.PCM_SIGNED) && af.getSampleSizeInBits() == 8 && af.isBigEndian()) name = "L8"; - - if(name != "") { - int id = PTIDAssigner.getDynamicID(name, af.getChannels(), af.getSampleRate()); - return new PayloadType.Audio(id, name, af.getChannels(), Math.round(af.getSampleRate())); - } - - return null; - } - - public float preferenceLevel(PayloadType pt) { - // TODO Auto-generated method stub - return 0; - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslationProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslationProvider.java deleted file mode 100644 index fe434cd25..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslationProvider.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import org.jivesoftware.smackx.jingle.PayloadType; - -public interface FormatTranslationProvider { - - public Object translate(Object sourceFormat, Class targetClass); - - public float preferenceLevel(PayloadType format); - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslator.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslator.java deleted file mode 100644 index 6c4b11e86..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/FormatTranslator.java +++ /dev/null @@ -1,91 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.util.ArrayList; -import java.util.Iterator; - -import javax.media.Format; -import javax.sound.sampled.AudioFormat; - -import org.jivesoftware.smackx.jingle.PayloadType; - -import sun.misc.Service; - -public class FormatTranslator { - - public static final float UNDEFINED_PREFERENCE_LEVEL = -1.0f; - - public static Object translate(Object sourceFormat, Class targetClass) { - - FormatTranslationProvider[] providers = getProviderArray(); - - for(int i = 0; i < providers.length; i++) { - Object result = providers[i].translate(sourceFormat, targetClass); - if(result != null) return result; - } - - return null; - } - - public static float preferenceLevel(PayloadType pt) { - - FormatTranslationProvider[] providers = getProviderArray(); - - for(int i = 0; i < providers.length; i++) { - float result = providers[i].preferenceLevel(pt); - if(result != UNDEFINED_PREFERENCE_LEVEL) return result; - } - - return UNDEFINED_PREFERENCE_LEVEL; - } - - public static AudioFormat toJSAudioFormat(Object sourceFormat) { - return (AudioFormat) translate(sourceFormat, AudioFormat.class); - } - - public static Format toJMFFormat(Object sourceFormat) { - return (Format) translate(sourceFormat, Format.class); - } - - public static PayloadType toPayloadType(Object sourceFormat) { - return (PayloadType) translate(sourceFormat, PayloadType.class); - } - - public static boolean equals(AudioFormat af1, AudioFormat af2) { - if(!af1.getEncoding().equals(af2.getEncoding())) return false; - if(af1.getChannels() != af2.getChannels()) return false; - if(!af1.getClass().equals(af2.getClass())) return false; - if(af1.getSampleSizeInBits() != af2.getSampleSizeInBits()) return false; - if(af1.getSampleRate() != af2.getSampleRate()) return false; - if(af1.isBigEndian() != af2.isBigEndian()) return false; - return true; - } - - public static boolean equals(javax.media.format.AudioFormat af1, javax.media.format.AudioFormat af2) { - if(!af1.isSameEncoding(af2)) return false; - if(af1.getChannels() != af2.getChannels()) return false; - if(!af1.getClass().equals(af2.getClass())) return false; - if(af1.getSampleSizeInBits() != af2.getSampleSizeInBits()) return false; - if(af1.getSampleRate() != af2.getSampleRate()) return false; - if(af1.getEndian() != af2.getEndian()) return false; - if(af1.getSigned() != af2.getSigned()) return false; - return true; - } - - private static FormatTranslationProvider[] getProviderArray() { - FormatTranslationProvider[] result = null; - - Iterator it = Service.providers(FormatTranslationProvider.class); - ArrayList al = new ArrayList(); - while(it.hasNext()) al.add(it.next()); - result = (FormatTranslationProvider[]) al.toArray(new FormatTranslationProvider[0]); - - //if none were found use default list - if(result.length == 0) { - FormatTranslationProvider[] defaultList = {new DefaultFormatTranslationProvider(), new SpeexFormatTranslationProvider()}; - return defaultList; - } - - return result; - } -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/PTIDAssigner.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/PTIDAssigner.java deleted file mode 100644 index 065ac5a0a..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/PTIDAssigner.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import org.jivesoftware.smackx.jingle.PayloadType; - -public class PTIDAssigner { - - private static Map dynamicIDs; - private static Set unassignedIDs; - - static { - dynamicIDs = new HashMap(); - unassignedIDs = new HashSet(); - -// initialise the Set of unassigned IDs, these are IDs in the static range that can be used -// for dynamic payload types. Values taken from table 4 and 5 in section 6 of RFC3551 - int[] ids = {20,21,22,23,24,27,29,30,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51, - 52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,68,69,70,71,77,78,79,80,81,82,83,84, - 85,86,87,88,89,90,91,92,93,94,95}; - for(int i = 0; i < ids.length; i++) unassignedIDs.add(new Integer(ids[i])); - } - - public synchronized static int getDynamicID(String name, int channels, float rate) { - - String lookupString = name + ", " + channels + ", " + rate; - -// has this pt already got an ID? - Integer result = (Integer) dynamicIDs.get(lookupString); - if(result != null) return result.intValue(); - -// If not then generate a new one. Make the new ID one higher than the highest one -// previously, or 97 if there are no previously assigned values. - int highest = 96; - Iterator it = dynamicIDs.values().iterator(); - while (it.hasNext()) { - Integer current = (Integer) it.next(); - if (current.intValue() > highest) highest = current.intValue(); - } - if(highest != 127) { - dynamicIDs.put(lookupString, new Integer(highest + 1)); - return highest + 1; - } else if(unassignedIDs.size() > 0) { -// if the highest PT ID was 127 then we have exhausted all the available IDs in the -// dynamic range and must start using unassigned IDs in the static range - Integer intID = (Integer) unassignedIDs.iterator().next(); - unassignedIDs.remove(intID); - dynamicIDs.put(lookupString, intID); - - return intID.intValue(); - } else return PayloadType.INVALID_PT; - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/SpeexFormatTranslationProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/SpeexFormatTranslationProvider.java deleted file mode 100644 index 0917780df..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/SpeexFormatTranslationProvider.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -//import javax.media.Format; -//import javax.media.format.AudioFormat; -//import javax.sound.sampled.AudioSystem; - -import org.jivesoftware.smackx.jingle.PayloadType; -//import org.xiph.speex.spi.SpeexEncoding; - -public class SpeexFormatTranslationProvider implements FormatTranslationProvider { - -// This class is mostly commented out to disable Speex in Jingle media. This is done because -// at the moment Speex decoding and encoding doesn't quite work. Once this is fixed then this -// code can all be uncommented to reenable Speex support. - -// 0 1 2 3 4 5 6 7 8 9 10 -// private static final boolean[] non_vbr_qualities = {false, false, false, true, false, false, false, true, false, false, true}; -// private static final boolean[] vbr_qualities = {false, false, false, true, false, false, false, true, false, false, true}; - - public Object translate(Object sourceFormat, Class targetClass) { -/* if(targetClass == AudioFormat.class || targetClass == Format.class) { - if(sourceFormat instanceof javax.sound.sampled.AudioFormat) - return toJMFAudioFormat((javax.sound.sampled.AudioFormat) sourceFormat); - - } else if(targetClass == javax.sound.sampled.AudioFormat.class) { - if(sourceFormat instanceof PayloadType.Audio) - return toJSAudioFormat((PayloadType.Audio) sourceFormat); - - else if(sourceFormat instanceof AudioFormat) - return toJSAudioFormat((AudioFormat) sourceFormat); - - } else if(targetClass == PayloadType.class || targetClass == PayloadType.Audio.class) { - if(sourceFormat instanceof javax.sound.sampled.AudioFormat) - return toPayloadType((javax.sound.sampled.AudioFormat) sourceFormat); - } - -*/ return null; - } - -/* private AudioFormat toJMFAudioFormat(javax.sound.sampled.AudioFormat af) { - if(af.getEncoding() instanceof SpeexEncoding && allowed(af.getEncoding().toString())) { - return new AudioFormat(af.getEncoding().toString(), af.getSampleRate(), AudioFormat.NOT_SPECIFIED, af.getChannels()); - } - return null; - } - - private javax.sound.sampled.AudioFormat toJSAudioFormat(PayloadType.Audio pta) { - if(pta.getName().startsWith("SPEEX") && allowed(pta.getName())) { - SpeexEncoding encoding = getEncoding(pta.getName()); - return new javax.sound.sampled.AudioFormat(encoding, pta.getClockRate(), AudioSystem.NOT_SPECIFIED, - pta.getChannels(), AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED, false); - } - return null; - } - - private javax.sound.sampled.AudioFormat toJSAudioFormat(AudioFormat af) { - if(af.getEncoding().startsWith("SPEEX") && allowed(af.getEncoding())) { - SpeexEncoding encoding = getEncoding(af.getEncoding()); - if(encoding != null) return new javax.sound.sampled.AudioFormat(encoding, (float) af.getSampleRate(), AudioSystem.NOT_SPECIFIED, - af.getChannels(), AudioSystem.NOT_SPECIFIED, AudioSystem.NOT_SPECIFIED, false); - } - return null; - } - - private PayloadType toPayloadType(javax.sound.sampled.AudioFormat af) { - if(af.getEncoding() instanceof SpeexEncoding && allowed(af.getEncoding().toString())) { - int id = PTIDAssigner.getDynamicID(af.getEncoding().toString(), af.getChannels(), af.getSampleRate()); - return new PayloadType.Audio(id, af.getEncoding().toString(), af.getChannels(), Math.round(af.getSampleRate())); - } - return null; - }*/ - - public float preferenceLevel(PayloadType pt) { - if(!pt.getName().startsWith("SPEEX")) - return FormatTranslator.UNDEFINED_PREFERENCE_LEVEL; - else { - - } - return FormatTranslator.UNDEFINED_PREFERENCE_LEVEL; - } - -/* private static SpeexEncoding getEncoding(String speexString) { - SpeexEncoding speexEnc = null; - - if(allowed(speexString)) { - if(speexString.equals("SPEEX_quality_0")) speexEnc = SpeexEncoding.SPEEX_Q0; - else if(speexString.equals("SPEEX_quality_1")) speexEnc = SpeexEncoding.SPEEX_Q1; - else if(speexString.equals("SPEEX_quality_2")) speexEnc = SpeexEncoding.SPEEX_Q2; - else if(speexString.equals("SPEEX_quality_3")) speexEnc = SpeexEncoding.SPEEX_Q3; - else if(speexString.equals("SPEEX_quality_4")) speexEnc = SpeexEncoding.SPEEX_Q4; - else if(speexString.equals("SPEEX_quality_5")) speexEnc = SpeexEncoding.SPEEX_Q5; - else if(speexString.equals("SPEEX_quality_6")) speexEnc = SpeexEncoding.SPEEX_Q6; - else if(speexString.equals("SPEEX_quality_7")) speexEnc = SpeexEncoding.SPEEX_Q7; - else if(speexString.equals("SPEEX_quality_8")) speexEnc = SpeexEncoding.SPEEX_Q8; - else if(speexString.equals("SPEEX_quality_9")) speexEnc = SpeexEncoding.SPEEX_Q9; - else if(speexString.equals("SPEEX_quality_10")) speexEnc = SpeexEncoding.SPEEX_Q10; - else if(speexString.equals("SPEEX_VBR_quality_0")) speexEnc = SpeexEncoding.SPEEX_VBR0; - else if(speexString.equals("SPEEX_VBR_quality_1")) speexEnc = SpeexEncoding.SPEEX_VBR1; - else if(speexString.equals("SPEEX_VBR_quality_2")) speexEnc = SpeexEncoding.SPEEX_VBR2; - else if(speexString.equals("SPEEX_VBR_quality_3")) speexEnc = SpeexEncoding.SPEEX_VBR3; - else if(speexString.equals("SPEEX_VBR_quality_4")) speexEnc = SpeexEncoding.SPEEX_VBR4; - else if(speexString.equals("SPEEX_VBR_quality_5")) speexEnc = SpeexEncoding.SPEEX_VBR5; - else if(speexString.equals("SPEEX_VBR_quality_6")) speexEnc = SpeexEncoding.SPEEX_VBR6; - else if(speexString.equals("SPEEX_VBR_quality_7")) speexEnc = SpeexEncoding.SPEEX_VBR7; - else if(speexString.equals("SPEEX_VBR_quality_8")) speexEnc = SpeexEncoding.SPEEX_VBR8; - else if(speexString.equals("SPEEX_VBR_quality_9")) speexEnc = SpeexEncoding.SPEEX_VBR9; - else if(speexString.equals("SPEEX_VBR_quality_10")) speexEnc = SpeexEncoding.SPEEX_VBR10; - } - - return speexEnc; - } - - private static boolean allowed(String speexString) { - String[] split = speexString.split("_"); - if(split.length == 3) { - int index = Integer.parseInt(split[2]); - return non_vbr_qualities[index]; - } else if (split.length == 4) { - int index = Integer.parseInt(split[3]); - return vbr_qualities[index]; - } else return false; - - } -*/} - - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/StreamConverter.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/StreamConverter.java deleted file mode 100644 index 237d1ea38..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/jingle/media/util/StreamConverter.java +++ /dev/null @@ -1,60 +0,0 @@ -package org.jivesoftware.smackx.jingle.media.util; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import javax.media.format.AudioFormat; -import javax.media.protocol.DataSource; -import javax.media.protocol.PushBufferDataSource; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; - -public class StreamConverter { - - private static Map ais2ds = new HashMap(); - private static Map ds2ais = new HashMap(); - - public static DataSource toDataSource(AudioInputStream ais) { - DataSource result = (DataSource) ais2ds.get(ais); - if(result == null) { - result = new AISDataSource(ais); - try { - result.connect(); - result.start(); - } catch (IOException e) {} - ais2ds.put(ais, result); - } - return result; - } - - public static DataSource toDataSource(InputStream is) { - if(is instanceof AudioInputStream) - return toDataSource((AudioInputStream) is); - return null; - } - - public static AudioInputStream toAudioInputStream(DataSource ds) { - AudioInputStream result = (AudioInputStream) ds2ais.get(ds); - if(result == null) { - try { - AudioFormat af = (AudioFormat) ((PushBufferDataSource) ds).getStreams()[0].getFormat(); - result = new AudioInputStream(toInputStream(ds), FormatTranslator.toJSAudioFormat(af), AudioSystem.NOT_SPECIFIED); - } catch (Exception e) { - e.printStackTrace(); - return null; - } - ais2ds.put(ds, result); - } - return result; - } - - public static InputStream toInputStream(DataSource ds) { - if (ds instanceof PushBufferDataSource) { - return new DSInputStream((PushBufferDataSource) ds, 40*1024); - } else throw new Error("DataSource must be of class PushBufferDataSource"); - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/BasicResolver.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/BasicResolver.java deleted file mode 100644 index 984517d60..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/BasicResolver.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.jivesoftware.smackx.nat; - -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.SocketException; -import java.util.Enumeration; - -import org.jivesoftware.smack.XMPPException; - -/** - * Simple resolver. - */ -public class BasicResolver extends TransportResolver { - - /** - * Constructor. - */ - public BasicResolver() { - super(); - } - - /** - * Resolve the IP address. - * - * The BasicResolver takes the IP addresses of the interfaces and uses the - * first non-loopback address. - */ - public synchronized void resolve() throws XMPPException { - - setResolveInit(); - - clearCandidates(); - - Enumeration ifaces = null; - - try { - ifaces = NetworkInterface.getNetworkInterfaces(); - } catch (SocketException e) { - e.printStackTrace(); - } - - while (ifaces.hasMoreElements()) { - - NetworkInterface iface = (NetworkInterface) ifaces.nextElement(); - Enumeration iaddresses = iface.getInetAddresses(); - - while (iaddresses.hasMoreElements()) { - InetAddress iaddress = (InetAddress) iaddresses.nextElement(); - if (!iaddress.isLoopbackAddress() && !iaddress.isLinkLocalAddress()) { - addCandidate(new TransportCandidate.Fixed(iaddress.getHostName(), 0)); - } - } - } - - setResolveEnd(); - } - - public void cancel() throws XMPPException { - // Nothing to do here - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/FixedResolver.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/FixedResolver.java deleted file mode 100644 index c4fdc2d58..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/FixedResolver.java +++ /dev/null @@ -1,51 +0,0 @@ -package org.jivesoftware.smackx.nat; - -import org.jivesoftware.smack.XMPPException; - -/** - * Specialization of the BasicResolver. The FixedResolver is a resolver where - * the external address and port are previously known when the object is - * initialized. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public class FixedResolver extends BasicResolver { - - TransportCandidate fixedCandidate; - - /** - * Constructor. - */ - public FixedResolver(final String ip, final int port) { - super(); - setFixedCandidate(ip, port); - } - - /** - * Create a basic resolver, where we provide the IP and port. - * - * @param ip an IP address - * @param port a port - */ - public void setFixedCandidate(final String ip, final int port) { - fixedCandidate = new TransportCandidate.Fixed(ip, port); - } - - /** - * Resolve the IP address. - */ - public synchronized void resolve() throws XMPPException { - - if (!isResolving()) { - setResolveInit(); - - clearCandidates(); - - if (fixedCandidate != null) { - addCandidate(fixedCandidate); - } - - setResolveEnd(); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/STUNResolver.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/STUNResolver.java deleted file mode 100644 index 47ef7e1eb..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/STUNResolver.java +++ /dev/null @@ -1,485 +0,0 @@ -package org.jivesoftware.smackx.nat; - -import java.io.IOException; -import java.net.InetAddress; -import java.net.NetworkInterface; -import java.net.ServerSocket; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Enumeration; -import org.jivesoftware.smack.XMPPException; -import org.xmlpull.v1.*; -import org.xmlpull.mxp1.MXParser; - -import java.net.URL; - -import de.javawi.jstun.test.BindingLifetimeTest; -import de.javawi.jstun.test.DiscoveryInfo; -import de.javawi.jstun.test.DiscoveryTest; - -/** - * Transport resolver using the STUN library. - * - * @author Alvaro Saurin - */ -public class STUNResolver extends TransportResolver { - - // The filename where the STUN servers are stored. - public final static String STUNSERVERS_FILENAME = "META-INF/stun-config.xml"; - - // Fallback values when we don't have any STUN server to use... - private final static String FALLBACKHOSTNAME = "stun.xten.net"; - - private final static int FALLBACKHOSTPORT = 3478; - - // Current STUN server we are using - private STUNService currentServer; - - private Thread resolverThread; - - private int defaultPort; - - /** - * Constructor with default STUN server. - */ - public STUNResolver() { - super(); - - this.defaultPort = 0; - this.currentServer = new STUNService(); - } - - /** - * Constructor with a default port. - * - * @param defaultPort Port to use by default. - */ - public STUNResolver(int defaultPort) { - this(); - - this.defaultPort = defaultPort; - } - - /** - * Return true if the service is working. - * - * @see org.jivesoftware.smackx.nat.TransportResolver#isResolving() - */ - public boolean isResolving() { - return super.isResolving() && resolverThread != null; - } - - /** - * Set the STUN server name and port - * - * @param ip the STUN server name - * @param port the STUN server port - */ - public void setSTUNService(final String ip, final int port) { - currentServer = new STUNService(ip, port); - } - - /** - * Get the name of the current STUN server. - * - * @return the name of the STUN server - */ - public String getCurrentServerName() { - if (!currentServer.isNull()) { - return currentServer.getHostname(); - } else { - return null; - } - } - - /** - * Get the port of the current STUN server. - * - * @return the port of the STUN server - */ - public int getCurrentServerPort() { - if (!currentServer.isNull()) { - return currentServer.getPort(); - } else { - return 0; - } - } - - /** - * Load the STUN configuration from a stream. - * - * @param stunConfigStream An InputStream with the configuration file. - * @return A list of loaded servers - */ - public ArrayList loadSTUNServers(final java.io.InputStream stunConfigStream) { - ArrayList serversList = new ArrayList(); - String serverName; - int serverPort; - - try { - XmlPullParser parser = new MXParser(); - parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true); - parser.setInput(stunConfigStream, "UTF-8"); - - int eventType = parser.getEventType(); - do { - if (eventType == XmlPullParser.START_TAG) { - - // Parse a STUN server definition - if (parser.getName().equals("stunServer")) { - - serverName = null; - serverPort = -1; - - // Parse the hostname - parser.next(); - parser.next(); - serverName = parser.nextText(); - - // Parse the port - parser.next(); - parser.next(); - try { - serverPort = Integer.parseInt(parser.nextText()); - } catch (Exception e) { - } - - // If we have a valid hostname and port, add - // it to the list. - if (serverName != null && serverPort != -1) { - STUNService service = new STUNService(serverName, serverPort); - - serversList.add(service); - } - } - } - eventType = parser.next(); - - } while (eventType != XmlPullParser.END_DOCUMENT); - - } catch (XmlPullParserException e) { - e.printStackTrace(); - } catch (IOException e) { - e.printStackTrace(); - } - - currentServer = bestSTUNServer(serversList); - - return serversList; - } - - /** - * Load a list of services: STUN servers and ports. Some public STUN servers - * are: - * - * <pre> - * iphone-stun.freenet.de:3478 - * larry.gloo.net:3478 - * stun.xten.net:3478 - * stun.fwdnet.net - * stun.fwd.org (no DNS SRV record) - * stun01.sipphone.com (no DNS SRV record) - * stun.softjoys.com (no DNS SRV record) - * stun.voipbuster.com (no DNS SRV record) - * stun.voxgratia.org (no DNS SRV record) - * stun.noc.ams-ix.net - * </pre> - * - * This list should be contained in a file in the "META-INF" directory - * - * @return a list of services - */ - public ArrayList loadSTUNServers() { - ArrayList serversList = new ArrayList(); - - // Load the STUN configuration - try { - // Get an array of class loaders to try loading the config from. - ClassLoader[] classLoaders = new ClassLoader[2]; - classLoaders[0] = new STUNResolver().getClass().getClassLoader(); - classLoaders[1] = Thread.currentThread().getContextClassLoader(); - - for (int i = 0; i < classLoaders.length; i++) { - Enumeration stunConfigEnum = classLoaders[i] - .getResources(STUNSERVERS_FILENAME); - - while (stunConfigEnum.hasMoreElements() && serversList.isEmpty()) { - URL url = (URL) stunConfigEnum.nextElement(); - java.io.InputStream stunConfigStream = null; - - stunConfigStream = url.openStream(); - serversList.addAll(loadSTUNServers(stunConfigStream)); - stunConfigStream.close(); - } - } - } catch (Exception e) { - e.printStackTrace(); - } - - // If the list of candidates is empty, add at least one default server - if (serversList.isEmpty()) { - serversList.add(new STUNService(FALLBACKHOSTNAME, FALLBACKHOSTPORT)); - } - - return serversList; - } - - /** - * Get the best usable STUN server from a list. - * - * @return the best STUN server that can be used. - */ - private STUNService bestSTUNServer(final ArrayList listServers) { - if (listServers.isEmpty()) { - return null; - } else { - // TODO: this should use some more advanced criteria... - return (STUNService) listServers.get(0); - } - } - - /** - * Obtain a free port we can use. - * - * @return A free port number. - */ - private int getFreePort() { - ServerSocket ss; - int freePort = 0; - try { - ss = new ServerSocket(0); - freePort = ss.getLocalPort(); - ss.close(); - } catch (IOException e) { - e.printStackTrace(); - } - - return freePort; - } - - /** - * Resolve the IP and obtain a valid transport method. - */ - public synchronized void resolve() throws XMPPException { - if (!isResolving()) { - // Get the best STUN server available - if (currentServer.isNull()) { - loadSTUNServers(); - } - - // We should have a valid STUN server by now... - if (!currentServer.isNull()) { - - setResolveInit(); - - clearCandidates(); - - resolverThread = new Thread(new Runnable() { - public void run() { - // Iterate through the list of interfaces, and ask - // to the STUN server for our address. - try { - Enumeration ifaces = NetworkInterface.getNetworkInterfaces(); - String candAddress; - int candPort; - - while (ifaces.hasMoreElements()) { - - NetworkInterface iface = (NetworkInterface) ifaces - .nextElement(); - Enumeration iaddresses = iface.getInetAddresses(); - - while (iaddresses.hasMoreElements()) { - InetAddress iaddress = (InetAddress) iaddresses - .nextElement(); - if (!iaddress.isLoopbackAddress() - && !iaddress.isLinkLocalAddress()) { - - // Reset the candidate - candAddress = null; - candPort = -1; - - DiscoveryTest test = new DiscoveryTest(iaddress, - currentServer.getHostname(), - currentServer.getPort()); - try { - // Run the tests and get the - // discovery - // information, where all the - // info is stored... - DiscoveryInfo di = test.test(); - - candAddress = di.getPublicIP() - .getHostAddress(); - - // Get a valid port - if (defaultPort == 0) { - candPort = getFreePort(); - } else { - candPort = defaultPort; - } - - // If we have a valid candidate, - // add it to the list. - if (candAddress != null && candPort >= 0) { - addCandidate(new TransportCandidate.Fixed( - candAddress, candPort)); - } - } catch (Exception e) { - e.printStackTrace(); - } - } - } - } - } catch (SocketException e) { - e.printStackTrace(); - } finally { - setResolveEnd(); - } - } - }, "Waiting for all the transport candidates checks..."); - - resolverThread.setName("STUN resolver"); - resolverThread.start(); - } else { - throw new IllegalStateException("No valid STUN server found."); - } - } - } - - /** - * Cancel any operation. - * - * @see org.jivesoftware.smackx.nat.TransportResolver#cancel() - */ - public synchronized void cancel() throws XMPPException { - if (isResolving()) { - resolverThread.interrupt(); - setResolveEnd(); - } - } - - /** - * Clear the list of candidates and start the resolution again. - * - * @see org.jivesoftware.smackx.nat.TransportResolver#clear() - */ - public synchronized void clear() throws XMPPException { - this.defaultPort = 0; - super.clear(); - } - - /** - * STUN service definition. - */ - private class STUNService { - - private String hostname; // The hostname of the service - - private int port; // The port number - - /** - * Basic constructor, with the hostname and port - * - * @param hostname The hostname - * @param port The port - */ - public STUNService(final String hostname, final int port) { - super(); - - this.hostname = hostname; - this.port = port; - } - - /** - * Default constructor, without name and port. - */ - public STUNService() { - this(null, -1); - } - - /** - * Get the host name of the STUN service. - * - * @return The host name - */ - public String getHostname() { - return hostname; - } - - /** - * Set the hostname of the STUN service. - * - * @param hostname The host name of the service. - */ - public void setHostname(final String hostname) { - this.hostname = hostname; - } - - /** - * Get the port of the STUN service - * - * @return The port number where the STUN server is waiting. - */ - public int getPort() { - return port; - } - - /** - * Set the port number for the STUN service. - * - * @param port The port number. - */ - public void setPort(final int port) { - this.port = port; - } - - /** - * Basic format test: the service is not null. - * - * @return true if the hostname and port are null - */ - public boolean isNull() { - if (hostname == null) { - return true; - } else if (hostname.length() == 0) { - return true; - } else if (port < 0) { - return true; - } else { - return false; - } - } - - /** - * Check a binding with the STUN currentServer. - * - * Note: this function blocks for some time, waiting for a response. - * - * @return true if the currentServer is usable. - */ - public boolean checkBinding() { - boolean result = false; - - try { - BindingLifetimeTest binding = new BindingLifetimeTest(hostname, port); - - binding.test(); - - while (true) { - Thread.sleep(5000); - if (binding.getLifetime() != -1) { - if (binding.isCompleted()) { - return true; - } - } else { - break; - } - } - } catch (Exception e) { - } - - return result; - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportCandidate.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportCandidate.java deleted file mode 100644 index 46c558945..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportCandidate.java +++ /dev/null @@ -1,703 +0,0 @@ -/** - * $RCSfile: TransportCandidate.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:13:55 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.nat; - -/** - * Transport candidate. - * - * </p> - * - * A candidate represents the possible transport for data interchange between - * the two endpoints. - * - * </p> - * - * @author Alvaro Saurin - */ -public abstract class TransportCandidate { - - private String name; - - private String ip; // IP address - - private int port; // Port to use, or 0 for any port - - private int generation; - - /** - * Empty constructor - */ - public TransportCandidate() { - this(null, 0, 0); - } - - /** - * Constructor with IP address and port - * - * @param ip The IP address. - * @param port The port number. - */ - public TransportCandidate(final String ip, final int port) { - this(ip, port, 0); - } - - /** - * Constructor with IP address and port - * - * @param ip The IP address. - * @param port The port number. - * @parame generation The generation - */ - public TransportCandidate(final String ip, final int port, final int generation) { - this.ip = ip; - this.port = port; - this.generation = generation; - } - - /** - * Return true if the candidate is not valid. - * - * @return true if the candidate is null. - */ - public boolean isNull() { - if (ip == null) { - return true; - } else if (ip.length() == 0) { - return true; - } else if (port < 0) { - return true; - } else { - return false; - } - } - - /** - * Get the IP - * - * @return the IP address - */ - public String getIP() { - return ip; - } - - /** - * Set the IP address. - * - * @param ip the IP address - */ - public void setIP(final String ip) { - this.ip = ip; - } - - /** - * Get the port, or 0 for any port. - * - * @return the port or 0 - */ - public int getPort() { - return port; - } - - /** - * Set the port, using 0 for any port - * - * @param port the port - */ - public void setPort(final int port) { - this.port = port; - } - - /** - * Get the generation for a transportElement definition - * - * @return the generation - */ - public int getGeneration() { - return generation; - } - - /** - * Set the generation for a transportElement definition. - * - * @param generation the generation number - */ - public void setGeneration(final int generation) { - this.generation = generation; - } - - /** - * Get the name used for identifying this transportElement method (optional) - * - * @return a name used for identifying this transportElement (ie, - * "myrtpvoice1") - */ - public String getName() { - return name; - } - - /** - * Set a name for identifying this transportElement. - * - * @param name the name used for the transportElement - */ - public void setName(final String name) { - this.name = name; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final TransportCandidate other = (TransportCandidate) obj; - if (generation != other.generation) { - return false; - } - if (getIP() == null) { - if (other.getIP() != null) { - return false; - } - } else if (!getIP().equals(other.getIP())) { - return false; - } - if (getName() == null) { - if (other.getName() != null) { - return false; - } - } else if (!getName().equals(other.getName())) { - return false; - } - if (getPort() != other.getPort()) { - return false; - } - return true; - } - - /** - * Fixed transport candidate - */ - public static class Fixed extends TransportCandidate { - public Fixed() { - super(); - } - - /** - * Constructor with IP address and port - * - * @param ip The IP address. - * @param port The port number. - */ - public Fixed(final String ip, final int port) { - super(ip, port); - } - - /** - * Constructor with IP address and port - * - * @param ip The IP address. - * @param port The port number. - * @parame generation The generation - */ - public Fixed(final String ip, final int port, final int generation) { - super(ip, port, generation); - } - } - - /** - * Ice candidate. - */ - public static class Ice extends TransportCandidate implements Comparable { - - private String id; // An identification - - private String password; - - private String username; - - private int preference; - - private Protocol proto; - - private Channel channel; - - private int network; - - public Ice() { - super(); - } - - /** - * Constructor with the basic elements of a transport definition. - * - * @param ip the IP address to use as a local address - * @param generation used to keep track of the candidates - * @param network used for diagnostics (used when the machine has - * several NICs) - * @param password user name, as it is used in ICE - * @param port the port at the candidate IP address - * @param username user name, as it is used in ICE - * @param preference preference for this transportElement, as it is used - * in ICE - */ - public Ice(final String ip, final int generation, final int network, - final String password, final int port, final String username, - final int preference) { - super(ip, port, generation); - - proto = new Protocol(""); - channel = new Channel(""); - - this.network = network; - this.password = password; - this.username = username; - this.preference = preference; - } - - /** - * Get the ID - * - * @return the id - */ - public String getId() { - return id; - } - - /** - * Set the ID - * - * @param id the id to set - */ - public void setId(final String id) { - this.id = id; - } - - /** - * Get the protocol used for the transmission - * - * @return the protocol used for transmission - */ - public Protocol getProto() { - return proto; - } - - /** - * Set the protocol for the transmission - * - * @param proto the protocol to use - */ - public void setProto(final Protocol proto) { - this.proto = proto; - } - - /** - * Get the network interface used for this connection - * - * @return the interface number - */ - public int getNetwork() { - return network; - } - - /** - * Set the interface for this connection - * - * @param network the interface number - */ - public void setNetwork(final int network) { - this.network = network; - } - - /** - * Get the password used by ICE - * - * @return a password - */ - public String getPassword() { - return password; - } - - /** - * Set the password used by ICE - * - * @param password a password - */ - public void setPassword(final String password) { - this.password = password; - } - - /** - * Get the username for this transportElement in ICE - * - * @return a username string - */ - public String getUsername() { - return username; - } - - /** - * Get the channel - * - * @return the channel associated - */ - public Channel getChannel() { - return channel; - } - - /** - * Set the channel for this transportElement - * - * @param channel the new channel - */ - public void setChannel(final Channel channel) { - this.channel = channel; - } - - /** - * Set the username for this transportElement in ICE - * - * @param username the username used in ICE - */ - public void setUsername(final String username) { - this.username = username; - } - - /** - * Get the preference number for this transportElement - * - * @return the preference for this transportElement - */ - public int getPreference() { - return preference; - } - - /** - * Set the preference order for this transportElement - * - * @param preference a number identifying the preference (as defined in - * ICE) - */ - public void setPreference(final int preference) { - this.preference = preference; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (!super.equals(obj)) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - - final Ice other = (Ice) obj; - if (getChannel() == null) { - if (other.getChannel() != null) { - return false; - } - } else if (!getChannel().equals(other.getChannel())) { - return false; - } - if (getId() == null) { - if (other.getId() != null) { - return false; - } - } else if (!getId().equals(other.getId())) { - return false; - } - if (getNetwork() != other.getNetwork()) { - return false; - } - if (getPassword() == null) { - if (other.getPassword() != null) { - return false; - } - } else if (!getPassword().equals(other.password)) { - return false; - } - if (getPreference() != other.getPreference()) { - return false; - } - if (getProto() == null) { - if (other.getProto() != null) { - return false; - } - } else if (!getProto().equals(other.getProto())) { - return false; - } - if (getUsername() == null) { - if (other.getUsername() != null) { - return false; - } - } else if (!getUsername().equals(other.getUsername())) { - return false; - } - return true; - } - - public boolean isNull() { - if (super.isNull()) { - return true; - } else if (getProto().isNull()) { - return true; - } else if (getChannel().isNull()) { - return true; - } - return false; - } - - /** - * Compare the to other Transport candidate. - * - * @param arg another Transport candidate - * @return a negative integer, zero, or a positive integer as this - * object is less than, equal to, or greater than the specified - * object - */ - public int compareTo(final Object arg) { - if (arg instanceof TransportCandidate.Ice) { - TransportCandidate.Ice tc = (TransportCandidate.Ice) arg; - if (getPreference() < tc.getPreference()) { - return -1; - } else if (getPreference() > tc.getPreference()) { - return 1; - } - } - return 0; - } - } - - /** - * Type-safe enum for the transportElement protocol - */ - public static class Protocol { - - public static final Protocol UDP = new Protocol("udp"); - - public static final Protocol TCP = new Protocol("tcp"); - - public static final Protocol TCPACT = new Protocol("tcp-act"); - - public static final Protocol TCPPASS = new Protocol("tcp-pass"); - - public static final Protocol SSLTCP = new Protocol("ssltcp"); - - private String value; - - public Protocol(final String value) { - this.value = value; - } - - public String toString() { - return value; - } - - /** - * Returns the Protocol constant associated with the String value. - */ - public static Protocol fromString(String value) { - if (value == null) { - return UDP; - } - value = value.toLowerCase(); - if (value.equals("udp")) { - return UDP; - } else if (value.equals("tcp")) { - return TCP; - } else if (value.equals("tcp-act")) { - return TCPACT; - } else if (value.equals("tcp-pass")) { - return TCPPASS; - } else if (value.equals("ssltcp")) { - return SSLTCP; - } else { - return UDP; - } - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Protocol other = (Protocol) obj; - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } - - /** - * Return true if the protocol is not valid. - * - * @return true if the protocol is null - */ - public boolean isNull() { - if (value == null) { - return true; - } else if (value.length() == 0) { - return true; - } else { - return false; - } - } - } - - /** - * Type-safe enum for the transportElement channel - */ - public static class Channel { - - public static final Channel MYRTPVOICE = new Channel("myrtpvoice"); - - public static final Channel MYRTCPVOICE = new Channel("myrtcpvoice"); - - private String value; - - public Channel(final String value) { - this.value = value; - } - - public String toString() { - return value; - } - - /** - * Returns the MediaChannel constant associated with the String value. - */ - public static Channel fromString(String value) { - if (value == null) { - return MYRTPVOICE; - } - value = value.toLowerCase(); - if (value.equals("myrtpvoice")) { - return MYRTPVOICE; - } else if (value.equals("tcp")) { - return MYRTCPVOICE; - } else { - return MYRTPVOICE; - } - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Channel other = (Channel) obj; - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } - - /** - * Return true if the channel is not valid. - * - * @return true if the channel is null - */ - public boolean isNull() { - if (value == null) { - return true; - } else if (value.length() == 0) { - return true; - } else { - return false; - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolver.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolver.java deleted file mode 100644 index 726e6363e..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolver.java +++ /dev/null @@ -1,390 +0,0 @@ -/** - * $RCSfile: TransportResolver.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:13:55 $ - * - * Copyright (C) 2002-2006 Jive Software. All rights reserved. - * ==================================================================== - * The Jive Software License (based on Apache Software License, Version 1.1) - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. The end-user documentation included with the redistribution, - * if any, must include the following acknowledgment: - * "This product includes software developed by - * Jive Software (http://www.jivesoftware.com)." - * Alternately, this acknowledgment may appear in the software itself, - * if and wherever such third-party acknowledgments normally appear. - * - * 4. The names "Smack" and "Jive Software" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please - * contact webmaster@jivesoftware.com. - * - * 5. Products derived from this software may not be called "Smack", - * nor may "Smack" appear in their name, without prior written - * permission of Jive Software. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL JIVE SOFTWARE OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT - * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * ==================================================================== - */ - -package org.jivesoftware.smackx.nat; - -import java.net.InetAddress; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.jivesoftware.smack.XMPPException; - -/** - * A TransportResolver is used for obtaining a list of valid transport - * candidates. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class TransportResolver { - - // the time, in milliseconds, before a check aborts - public static final int CHECK_TIMEOUT = 2000; - - // Listeners for events - private final ArrayList listeners = new ArrayList(); - - // TRue if the resolver is working - private boolean resolving; - - // This will be true when all the transport candidates have been gathered... - private boolean resolved; - - // We store a list of candidates internally, just in case there are several - // possibilities. When the user asks for a transport, we return the best - // one. - protected final List candidates = new ArrayList(); - - // Remote candidates that are being checked - private final static ArrayList candidatesChecking = new ArrayList(); - - /** - * Default constructor. - */ - protected TransportResolver() { - super(); - - resolving = false; - resolved = false; - } - - /** - * Start the resolution. - */ - public abstract void resolve() throws XMPPException; - - /** - * Clear the list of candidates and start a new resolution process. - * - * @throws XMPPException - */ - public void clear() throws XMPPException { - cancel(); - candidates.clear(); - resolve(); - } - - /** - * Cancel any asynchronous resolution operation. - */ - public abstract void cancel() throws XMPPException; - - /** - * Return true if the resolver is working. - * - * @return true if the resolver is working. - */ - public boolean isResolving() { - return resolving; - } - - /** - * Return true if the resolver has finished the search for transport - * candidates. - * - * @return true if the search has finished - */ - public boolean isResolved() { - return resolved; - } - - /** - * Indicate the beggining of the resolution process. This method must be - * used by subclasses at the begining of their resolve() method. - */ - protected synchronized void setResolveInit() { - resolved = false; - resolving = true; - - triggerResolveInit(); - } - - /** - * Indicate the end of the resolution process. This method must be used by - * subclasses at the begining of their resolve() method. - */ - protected synchronized void setResolveEnd() { - resolved = true; - resolving = false; - - triggerResolveEnd(); - } - - /** - * Check if a transport candidate is usable. The transport resolver should - * check if the transport candidate the other endpoint has provided is - * usable. - * - * This method provides a basic check where it sends a "ping" to the remote - * address provided in the candidate. If the "ping" succedess, the candidate - * is accepted. Subclasses should provide better methods if they can... - * - * @param cand The transport candidate to test. - */ - public void check(final TransportCandidate cand) { - if (!candidatesChecking.contains(cand)) { - candidatesChecking.add(cand); - - Thread checkThread = new Thread(new Runnable() { - public void run() { - boolean isUsable; - - InetAddress candAddress; - try { - candAddress = InetAddress.getByName(cand.getIP()); - isUsable = candAddress.isReachable(CHECK_TIMEOUT); - } catch (Exception e) { - isUsable = false; - } - triggerCandidateChecked(cand, isUsable); - - candidatesChecking.remove(cand); - } - }, "Transport candidate check"); - - checkThread.setName("Transport candidate test"); - checkThread.start(); - } - } - - // Listeners management - - /** - * Add a transport resolver listener. - * - * @param li The transport resolver listener to be added. - */ - public void addListener(final TransportResolverListener li) { - synchronized (listeners) { - listeners.add(li); - } - } - - /** - * Removes a transport resolver listener. - * - * @param li The transport resolver listener to be removed - */ - public void removeListener(final TransportResolverListener li) { - synchronized (listeners) { - listeners.remove(li); - } - } - - /** - * Get the list of listeners - * - * @return the list of listeners - */ - public ArrayList getListenersList() { - synchronized (listeners) { - return new ArrayList(listeners); - } - } - - /** - * Trigger a new candidate added event. - * - * @param cand The candidate added to the list of candidates. - */ - protected void triggerCandidateAdded(final TransportCandidate cand) { - Iterator iter = getListenersList().iterator(); - while (iter.hasNext()) { - TransportResolverListener trl = (TransportResolverListener) iter.next(); - if (trl instanceof TransportResolverListener.Resolver) { - TransportResolverListener.Resolver li = (TransportResolverListener.Resolver) trl; - li.candidateAdded(cand); - } - } - } - - /** - * Trigger a new candidate checked event. - * - * @param cand The checked candidate. - * @param result The result. - */ - protected void triggerCandidateChecked(final TransportCandidate cand, - final boolean result) { - Iterator iter = getListenersList().iterator(); - while (iter.hasNext()) { - TransportResolverListener trl = (TransportResolverListener) iter.next(); - if (trl instanceof TransportResolverListener.Checker) { - TransportResolverListener.Checker li = (TransportResolverListener.Checker) trl; - li.candidateChecked(cand, result); - } - } - } - - /** - * Trigger a event notifying the initialization of the resolution process. - */ - private void triggerResolveInit() { - Iterator iter = getListenersList().iterator(); - while (iter.hasNext()) { - TransportResolverListener trl = (TransportResolverListener) iter.next(); - if (trl instanceof TransportResolverListener.Resolver) { - TransportResolverListener.Resolver li = (TransportResolverListener.Resolver) trl; - li.init(); - } - } - } - - /** - * Trigger a event notifying the obtention of all the candidates. - */ - private void triggerResolveEnd() { - Iterator iter = getListenersList().iterator(); - while (iter.hasNext()) { - TransportResolverListener trl = (TransportResolverListener) iter.next(); - if (trl instanceof TransportResolverListener.Resolver) { - TransportResolverListener.Resolver li = (TransportResolverListener.Resolver) trl; - li.end(); - } - } - } - - // Candidates management - - /** - * Clear the list of candidate - */ - protected void clearCandidates() { - synchronized (candidates) { - candidates.clear(); - } - } - - /** - * Add a new transport candidate - * - * @param cand The candidate to add - */ - protected void addCandidate(final TransportCandidate cand) { - synchronized (candidates) { - candidates.add(cand); - } - - // Notify the listeners - triggerCandidateAdded(cand); - } - - /** - * Get an iterator for the list of candidates - * - * @return an iterator - */ - public Iterator getCandidates() { - synchronized (candidates) { - return Collections.unmodifiableList(new ArrayList(candidates)).iterator(); - } - } - - /** - * Get the candididate with the highest preference. - * - * @return The best candidate, according to the preference order. - */ - public TransportCandidate getPreferredCandidate() { - TransportCandidate result = null; - - ArrayList cands = (ArrayList) getCandidatesList(); - if (cands.size() > 0) { - Collections.sort(cands); - // Return the last candidate - result = (TransportCandidate) cands.get(cands.size() - 1); - } - - return result; - } - - /** - * Get the numer of transport candidates. - * - * @return The length of the transport candidates list. - */ - public int getCandidateCount() { - synchronized (candidates) { - return candidates.size(); - } - } - - /** - * Get the list of candidates - * - * @return the list of transport candidates - */ - public List getCandidatesList() { - ArrayList result = null; - - synchronized (candidates) { - result = new ArrayList(candidates); - } - - return result; - } - - /** - * Get the n-th candidate - * - * @return a transport candidate - */ - public TransportCandidate getCandidate(final int i) { - TransportCandidate cand; - - synchronized (candidates) { - cand = (TransportCandidate) candidates.get(i); - } - return cand; - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolverListener.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolverListener.java deleted file mode 100644 index 367acc887..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/nat/TransportResolverListener.java +++ /dev/null @@ -1,38 +0,0 @@ -package org.jivesoftware.smackx.nat; - -public abstract interface TransportResolverListener { - /** - * Resolver listener. - */ - public interface Resolver extends TransportResolverListener { - /** - * The resolution process has been started. - */ - public void init(); - - /** - * A transport candidate has been added - * - * @param cand The transport candidate. - */ - public void candidateAdded(TransportCandidate cand); - - /** - * All the transport candidates have been obtained. - */ - public void end(); - } - - /** - * Resolver checker. - */ - public interface Checker extends TransportResolverListener { - /** - * A transport candidate has been checked. - * - * @param cand The transport candidate that has been checked. - * @oaram result True if the candidate is usable. - */ - public void candidateChecked(TransportCandidate cand, boolean result); - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java deleted file mode 100644 index 800e42898..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java +++ /dev/null @@ -1,589 +0,0 @@ -/** - * $RCSfile: Jingle.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:14:14 $ - * - * Copyright 2003-2004 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; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.jivesoftware.smack.packet.IQ; - -/** - * An Jingle sub-packet, which is used by XMPP clients to exchange info like - * descriptions and transports. <p/> The following link summarizes the - * requirements of Jingle IM: <a - * href="http://www.jabber.org/jeps/jep-0166.html">Valid tags</a>. - * <p> - * <p/> Warning: this is an non-standard protocol documented by <a - * href="http://www.jabber.org/jeps/jep-0166.html">JEP-166</a>. Because this is - * a non-standard protocol, it is subject to change. - * - * @author Alvaro Saurin - */ -public class Jingle extends IQ { - - // static - - public static final String NAMESPACE = "http://jabber.org/protocol/jingle"; - - public static final String NODENAME = "jingle"; - - // non-static - - private String sid; // The session id - - private Action action; // The action associated to the Jingle - - private String initiator; // The initiator as a "user@host/resource" - - private String responder; // The responder - - // Sub-elements of a Jingle object. - - private final List descriptions = new ArrayList(); - - private final List transports = new ArrayList(); - - private JingleContentInfo contentInfo; - - /** - * A constructor where the main components can be initialized. - */ - public Jingle(final List descs, final List trans, final JingleContentInfo mi, - final String sid) { - super(); - - if (descs != null) { - descriptions.addAll(descs); - } - - if (trans != null) { - transports.addAll(trans); - } - - setContentInfo(mi); - setSid(sid); - - // Set null all other fields in the packet - initiator = null; - responder = null; - action = null; - } - - /** - * Constructor with a description. - * - * @param descr a description - */ - public Jingle(final JingleContentDescription descr) { - super(); - - addDescription(descr); - - // Set null all other fields in the packet - initiator = null; - responder = null; - - // Some default values for the most common situation... - action = Jingle.Action.CONTENTINFO; - this.setType(IQ.Type.SET); - } - - /** - * Constructor with a transport. - * - * @param trans a transport - */ - public Jingle(final JingleTransport trans) { - super(); - - addTransport(trans); - - // Set null all other fields in the packet - initiator = null; - responder = null; - - // Some default values for the most common situation... - action = Jingle.Action.TRANSPORTINFO; - this.setType(IQ.Type.SET); - } - - /** - * Constructor with a content info. - * - * @param info The content info - */ - public Jingle(final JingleContentInfo info) { - super(); - - setContentInfo(info); - - // Set null all other fields in the packet - initiator = null; - responder = null; - - // Some default values for the most common situation... - action = Jingle.Action.CONTENTINFO; - this.setType(IQ.Type.SET); - } - - /** - * A constructor where the action can be specified. - * - * @param action The action. - */ - public Jingle(final Jingle.Action action) { - this(null, null, null, null); - this.action = action; - - // In general, a Jingle with an action is used in a SET packet... - this.setType(IQ.Type.SET); - } - - /** - * A constructor where the session ID can be specified. - * - * @param sid The session ID related to the negotiation. - * @see #setSid(String) - */ - public Jingle(final String sid) { - this(null, null, null, sid); - } - - /** - * The default constructor - */ - public Jingle() { - super(); - } - - /** - * Set the session ID related to this session. The session ID is a unique - * identifier generated by the initiator. This should match the XML Nmtoken - * production so that XML character escaping is not needed for characters - * such as &. - * - * @param sid the session ID - */ - public final void setSid(final String sid) { - this.sid = sid; - } - - /** - * Returns the session ID related to the session. The session ID is a unique - * identifier generated by the initiator. This should match the XML Nmtoken - * production so that XML character escaping is not needed for characters - * such as &. - * - * @return Returns the session ID related to the session. - * @see #setSid(String) - */ - public String getSid() { - return sid; - } - - /** - * Returns the XML element name of the extension sub-packet root element. - * Always returns "jingle" - * - * @return the XML element name of the packet extension. - */ - public static String getElementName() { - return NODENAME; - } - - /** - * Returns the XML namespace of the extension sub-packet root element. - * According the specification the namespace is always - * "http://jabber.org/protocol/jingle" - * - * @return the XML namespace of the packet extension. - */ - public static String getNamespace() { - return NAMESPACE; - } - - /** - * @return the audioInfo - */ - public JingleContentInfo getContentInfo() { - return contentInfo; - } - - /** - * @param contentInfo the audioInfo to set - */ - public void setContentInfo(final JingleContentInfo contentInfo) { - this.contentInfo = contentInfo; - } - - /** - * Get an iterator for the content descriptions - * - * @return the descriptions - */ - public Iterator getDescriptions() { - synchronized (descriptions) { - return Collections.unmodifiableList(new ArrayList(descriptions)).iterator(); - } - } - - /** - * Get an iterator for the content descriptions - * - * @return the descriptions - */ - public ArrayList getDescriptionsList() { - synchronized (descriptions) { - return new ArrayList(descriptions); - } - } - - /** - * Add a new content description. - * - * @param desc the descriptions to add - */ - public void addDescription(final JingleContentDescription desc) { - if (desc != null) { - synchronized (descriptions) { - descriptions.add(desc); - } - } - } - - /** - * Add a list of JingleContentDescription elements - * - * @param descsList the list of transports to add - */ - public void addDescriptions(final List descsList) { - if (descsList != null) { - synchronized (descriptions) { - descriptions.addAll(descsList); - } - } - } - - /** - * Get an iterator for the transport. - * - * @return the transports - */ - public Iterator getTransports() { - synchronized (transports) { - return Collections.unmodifiableList(new ArrayList(transports)).iterator(); - } - } - - /** - * Get the list of transports. - * - * @return the transports list. - */ - public ArrayList getTransportsList() { - synchronized (transports) { - return new ArrayList(transports); - } - } - - /** - * Add a new JingleTransport element - * - * @param trans the transports to add - */ - public void addTransport(final JingleTransport trans) { - if (trans != null) { - synchronized (transports) { - transports.add(trans); - } - } - } - - /** - * Add a list of JingleTransport elements - * - * @param transList the list of transports to add - */ - public void addTransports(final List transList) { - if (transList != null) { - synchronized (transports) { - transports.addAll(transList); - } - } - } - - /** - * Get the action specified in the packet - * - * @return the action - */ - public Action getAction() { - return action; - } - - /** - * Set the action in the packet - * - * @param action the action to set - */ - public void setAction(final Action action) { - this.action = action; - } - - /** - * Get the initiator. The initiator will be the full JID of the entity that - * has initiated the flow (which may be different to the "from" address in - * the IQ) - * - * @return the initiator - */ - public String getInitiator() { - return initiator; - } - - /** - * Set the initiator. The initiator must be the full JID of the entity that - * has initiated the flow (which may be different to the "from" address in - * the IQ) - * - * @param initiator the initiator to set - */ - public void setInitiator(final String initiator) { - this.initiator = initiator; - } - - /** - * Get the responder. The responder is the full JID of the entity that has - * replied to the initiation (which may be different to the "to" addresss in - * the IQ). - * - * @return the responder - */ - public String getResponder() { - return responder; - } - - /** - * Set the responder. The responder must be the full JID of the entity that - * has replied to the initiation (which may be different to the "to" - * addresss in the IQ). - * - * @param resp the responder to set - */ - public void setResponder(final String resp) { - responder = resp; - } - - /** - * Get a hash key for the session this packet belongs to. - * - * @param sid The session id - * @param initiator The initiator - * @return A hash key - */ - public static int getSessionHash(final String sid, final String initiator) { - final int PRIME = 31; - int result = 1; - result = PRIME * result + (initiator == null ? 0 : initiator.hashCode()); - result = PRIME * result + (sid == null ? 0 : sid.hashCode()); - return result; - } - - /** - * Return the XML representation of the packet. - * - * @return the XML string - */ - public String getChildElementXML() { - StringBuffer buf = new StringBuffer(); - - buf.append("<").append(getElementName()); - buf.append(" xmlns=\"").append(getNamespace()).append("\""); - if (getInitiator() != null) { - buf.append(" initiator=\"").append(getInitiator()).append("\""); - } - if (getResponder() != null) { - buf.append(" responder=\"").append(getResponder()).append("\""); - } - if (getAction() != null) { - buf.append(" action=\"").append(getAction()).append("\""); - } - if (getSid() != null) { - buf.append(" sid=\"").append(getSid()).append("\""); - } - buf.append(">"); - - // Look for possible payload types, and dump them. - synchronized (descriptions) { - for (int i = 0; i < descriptions.size(); i++) { - JingleContentDescription desc = (JingleContentDescription) descriptions - .get(i); - buf.append(desc.toXML()); - } - } - - // If the packet has transports, dump them. - synchronized (transports) { - for (int i = 0; i < transports.size(); i++) { - JingleTransport trans = (JingleTransport) transports.get(i); - buf.append(trans.toXML()); - } - } - - // and the same for audio media info - if (contentInfo != null) { - buf.append(contentInfo.toXML()); - } - - buf.append("</").append(getElementName()).append(">"); - return buf.toString(); - } - - /** - * The "action" in the jingle packet, as an enum. - */ - public static class Action { - - public static final Action CONTENTACCEPT = new Action("description-accept"); - - public static final Action CONTENTDECLINE = new Action("description-decline"); - - public static final Action CONTENTINFO = new Action("description-info"); - - public static final Action CONTENTMODIFY = new Action("description-modify"); - - public static final Action SESSIONACCEPT = new Action("session-accept"); - - public static final Action SESSIONINFO = new Action("session-info"); - - public static final Action SESSIONINITIATE = new Action("session-initiate"); - - public static final Action SESSIONREDIRECT = new Action("session-redirect"); - - public static final Action SESSIONEXTEND = new Action("session-extend"); - - public static final Action SESSIONREDUCE = new Action("session-reduce"); - - public static final Action SESSIONTERMINATE = new Action("session-terminate"); - - public static final Action TRANSPORTACCEPT = new Action("transport-accept"); - - public static final Action TRANSPORTDECLINE = new Action("transport-decline"); - - public static final Action TRANSPORTINFO = new Action("transport-info"); - - public static final Action TRANSPORTMODIFY = new Action("transport-modify"); - - private String value; - - public Action(final String value) { - this.value = value; - } - - /** - * Returns the String value for an Action. - */ - public String toString() { - return value; - } - - /** - * Returns a Action instance associated with the String value. - */ - public static Action fromString(String value) { - if (value != null) { - value = value.toLowerCase(); - if (value.equals("description-accept")) { - return CONTENTACCEPT; - } else if (value.equals("description-decline")) { - return CONTENTDECLINE; - } else if (value.equals("description-info")) { - return CONTENTINFO; - } else if (value.equals("description-modify")) { - return CONTENTMODIFY; - } else if (value.equals("session-accept")) { - return SESSIONACCEPT; - } else if (value.equals("session-info")) { - return SESSIONINFO; - } else if (value.equals("session-initiate")) { - return SESSIONINITIATE; - } else if (value.equals("session-redirect")) { - return SESSIONACCEPT; - } else if (value.equals("session-extend")) { - return SESSIONEXTEND; - } else if (value.equals("session-reduce")) { - return SESSIONREDUCE; - } else if (value.equals("session-terminate")) { - return SESSIONTERMINATE; - } else if (value.equals("transport-accept")) { - return TRANSPORTACCEPT; - } else if (value.equals("transport-decline")) { - return TRANSPORTDECLINE; - } else if (value.equals("transport-info")) { - return TRANSPORTINFO; - } else if (value.equals("transport-modify")) { - return TRANSPORTMODIFY; - } - } - return null; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - final int PRIME = 31; - int result = 1; - result = PRIME * result + (value == null ? 0 : value.hashCode()); - return result; - } - - /* - * (non-Javadoc) - * - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final Action other = (Action) obj; - if (value == null) { - if (other.value != null) { - return false; - } - } else if (!value.equals(other.value)) { - return false; - } - return true; - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentDescription.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentDescription.java deleted file mode 100644 index 7e74620e8..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentDescription.java +++ /dev/null @@ -1,279 +0,0 @@ -package org.jivesoftware.smackx.packet; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smackx.jingle.PayloadType; - -/** - * Jingle content description. - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class JingleContentDescription implements PacketExtension { - - // static - - public static final String NODENAME = "description"; - - // non-static - - private final List payloads = new ArrayList(); - - /** - * Creates a content description.. - */ - public JingleContentDescription() { - super(); - } - - /** - * Returns the XML element name of the element. - * - * @return the XML element name of the element. - */ - public String getElementName() { - return NODENAME; - } - - /** - * Return the namespace. - * - * @return The namespace - */ - public abstract String getNamespace(); - - /** - * Adds a audio payload type to the packet. - * - * @param pt the audio payload type to add. - */ - public void addJinglePayloadType(final JinglePayloadType pt) { - synchronized (payloads) { - payloads.add(pt); - } - } - - /** - * Adds a list of payloads to the packet. - * - * @param pts the payloads to add. - */ - public void addAudioPayloadTypes(final List pts) { - synchronized (payloads) { - Iterator ptIter = pts.iterator(); - while (ptIter.hasNext()) { - PayloadType.Audio pt = (PayloadType.Audio) ptIter.next(); - addJinglePayloadType(new JinglePayloadType.Audio(pt)); - } - } - } - - /** - * Returns an Iterator for the audio payloads in the packet. - * - * @return an Iterator for the audio payloads in the packet. - */ - public Iterator getJinglePayloadTypes() { - return Collections.unmodifiableList(getJinglePayloadTypesList()).iterator(); - } - - /** - * Returns a list for the audio payloads in the packet. - * - * @return a list for the audio payloads in the packet. - */ - public ArrayList getJinglePayloadTypesList() { - synchronized (payloads) { - return new ArrayList(payloads); - } - } - - /** - * Return the list of Payload types contained in the description. - * - * @return a list of PayloadType.Audio - */ - public ArrayList getAudioPayloadTypesList() { - ArrayList result = new ArrayList(); - Iterator jinglePtsIter = getJinglePayloadTypes(); - - while(jinglePtsIter.hasNext()) { - JinglePayloadType jpt = (JinglePayloadType) jinglePtsIter.next(); - if (jpt instanceof JinglePayloadType.Audio) { - JinglePayloadType.Audio jpta = (JinglePayloadType.Audio) jpt; - result.add(jpta.getPayloadType()); - } - } - - return result; - } - - /** - * Returns a count of the audio payloads in the Jingle packet. - * - * @return the number of audio payloads in the Jingle packet. - */ - public int getJinglePayloadTypesCount() { - synchronized (payloads) { - return payloads.size(); - } - } - - /** - * Convert a Jingle description to XML. - * - * @return a string with the XML representation - */ - public String toXML() { - StringBuffer buf = new StringBuffer(); - - synchronized (payloads) { - if (payloads.size() > 0) { - buf.append("<").append(getElementName()); - buf.append(" xmlns=\"").append(getNamespace()).append("\" >"); - - Iterator pt = payloads.listIterator(); - while (pt.hasNext()) { - JinglePayloadType pte = (JinglePayloadType) pt.next(); - buf.append(pte.toXML()); - } - buf.append("</").append(getElementName()).append(">"); - } - } - - return buf.toString(); - } - - /** - * Jingle audio description - */ - public static class Audio extends JingleContentDescription { - - public static final String NAMESPACE = "http://jabber.org/protocol/jingle/description/audio"; - - public Audio() { - super(); - } - - /** - * Utility constructor, with a JinglePayloadType - */ - public Audio(final JinglePayloadType pt) { - super(); - addJinglePayloadType(pt); - } - - public String getNamespace() { - return NAMESPACE; - } - } - - /** - * A payload type, contained in a descriptor. - * - * @author Alvaro Saurin - * - */ - public static class JinglePayloadType { - - public static final String NODENAME = "payload-type"; - - private PayloadType payload; - - /** - * Create a payload type. - * - * @param payload the payload - */ - public JinglePayloadType(final PayloadType payload) { - super(); - this.payload = payload; - } - - /** - * Create an empty payload type. - */ - public JinglePayloadType() { - this(null); - } - - /** - * Returns the XML element name of the element. - * - * @return the XML element name of the element. - */ - public static String getElementName() { - return NODENAME; - } - - /** - * Get the payload represented. - * - * @return the payload - */ - public PayloadType getPayloadType() { - return payload; - } - - /** - * Set the payload represented. - * - * @param payload the payload to set - */ - public void setPayload(final PayloadType payload) { - this.payload = payload; - } - - protected String getChildAttributes() { - return null; - } - - public String toXML() { - StringBuffer buf = new StringBuffer(); - - if (payload != null) { - buf.append("<").append(getElementName()).append(" "); - - // We covert here the payload type to XML - if (payload.getId() != PayloadType.INVALID_PT) { - buf.append(" id=\"").append(payload.getId()).append("\""); - } - if (payload.getName() != null) { - buf.append(" name=\"").append(payload.getName()).append("\""); - } - if (payload.getChannels() != 0) { - buf.append(" channels=\"").append(payload.getChannels()).append("\""); - } - if (getChildAttributes() != null) { - buf.append(getChildAttributes()); - } - buf.append("/>"); - } - return buf.toString(); - } - - /** - * Audio payload type element - */ - public static class Audio extends JinglePayloadType { - public Audio(final PayloadType.Audio audio) { - super(audio); - } - - protected String getChildAttributes() { - StringBuffer buf = new StringBuffer(); - PayloadType pt = getPayloadType(); - if (pt instanceof PayloadType.Audio) { - PayloadType.Audio pta = (PayloadType.Audio) pt; - - buf.append(" clockrate=\"").append(pta.getClockRate()).append("\" "); - } - return buf.toString(); - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentInfo.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentInfo.java deleted file mode 100644 index 44f62121b..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleContentInfo.java +++ /dev/null @@ -1,138 +0,0 @@ -package org.jivesoftware.smackx.packet; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smackx.jingle.ContentInfo; - -/** - * Jingle content info - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public class JingleContentInfo implements PacketExtension { - - protected ContentInfo mediaInfoElement; - - private String namespace; - - /** - * Empty constructor, with no media info. - */ - public JingleContentInfo() { - this(null); - } - - /** - * Constructor with a media info - * - * @param mediaInfoElement MediaInfo element - */ - public JingleContentInfo(final ContentInfo mediaInfoElement) { - super(); - this.mediaInfoElement = mediaInfoElement; - } - - /** - * Get the media info element. - * - * @return the mediaInfoElement - */ - public ContentInfo getMediaInfo() { - return mediaInfoElement; - } - - /** - * Get the element name - */ - public String getElementName() { - // Media info is supposed to be just a single-word command... - return getMediaInfo().toString(); - } - - /** - * Set the name space. - * - * @param ns the namespace - */ - protected void setNamespace(final String ns) { - namespace = ns; - } - - /** - * Get the publilc namespace - */ - public String getNamespace() { - return namespace; - } - - public String toXML() { - StringBuffer buf = new StringBuffer(); - buf.append("<").append(getElementName()).append(" xmlns=\""); - buf.append(getNamespace()).append("\" "); - buf.append("/>"); - return buf.toString(); - } - - /** - * Transport part of a Jingle packet. - */ - public static class Audio extends JingleContentInfo { - - public static final String NAMESPACE = "http://jabber.org/protocol/jingle/info/audio"; - - public Audio(final ContentInfo mi) { - super(mi); - setNamespace(NAMESPACE); - } - - public String getNamespace() { - return NAMESPACE; - } - - // Subclasses: specialize the Audio media info... - - /** - * Busy media info. - */ - public static class Busy extends Audio { - public Busy() { - super(ContentInfo.Audio.BUSY); - } - } - - /** - * Hold media info. - */ - public static class Hold extends Audio { - public Hold() { - super(ContentInfo.Audio.HOLD); - } - } - - /** - * Mute media info. - */ - public static class Mute extends Audio { - public Mute() { - super(ContentInfo.Audio.MUTE); - } - } - - /** - * Queued media info. - */ - public static class Queued extends Audio { - public Queued() { - super(ContentInfo.Audio.QUEUED); - } - } - - /** - * Ringing media info. - */ - public static class Ringing extends Audio { - public Ringing() { - super(ContentInfo.Audio.RINGING); - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleError.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleError.java deleted file mode 100644 index 1a4b2d298..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleError.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.jivesoftware.smackx.packet; - -import org.jivesoftware.smack.packet.PacketExtension; - -public class JingleError implements PacketExtension { - - public static String NAMESPACE = "http://jabber.org/protocol/jingle#error"; - - public static final JingleError OUT_OF_ORDER = new JingleError("out-of-order"); - - public static final JingleError UNKNOWN_SESSION = new JingleError("unknown-session"); - - public static final JingleError UNSUPPORTED_CONTENT = new JingleError( - "unsupported-content"); - - public static final JingleError UNSUPPORTED_TRANSPORTS = new JingleError( - "unsupported-transports"); - - // Non standard error messages - - public static final JingleError NO_COMMON_PAYLOAD = new JingleError( - "no-common-payload"); - - public static final JingleError NEGOTIATION_ERROR = new JingleError( - "negotiation-error"); - - public static final JingleError MALFORMED_STANZA = new JingleError("malformed-stanza"); - - private String message; - - /** - * Creates a new error with the specified code and message. - * - * @param message a message describing the error. - */ - public JingleError(final String message) { - this.message = message; - } - - /** - * Returns the message describing the error, or null if there is no message. - * - * @return the message describing the error, or null if there is no message. - */ - public String getMessage() { - return message; - } - - /** - * Returns the error as XML. - * - * @return the error as XML. - */ - public String toXML() { - StringBuffer buf = new StringBuffer(); - if (message != null) { - buf.append("<error type=\"cancel\">"); - buf.append("<").append(message).append(" xmlns=\"").append(NAMESPACE).append( - "\"/>"); - buf.append("</error>"); - } - return buf.toString(); - } - - /** - * Returns a Action instance associated with the String value. - */ - public static JingleError fromString(String value) { - if (value != null) { - value = value.toLowerCase(); - if (value.equals("out-of-order")) { - return OUT_OF_ORDER; - } else if (value.equals("unknown-session")) { - return UNKNOWN_SESSION; - } else if (value.equals("unsupported-content")) { - return UNSUPPORTED_CONTENT; - } else if (value.equals("unsupported-transports")) { - return UNSUPPORTED_TRANSPORTS; - } else if (value.equals("no-common-payload")) { - return NO_COMMON_PAYLOAD; - } else if (value.equals("negotiation-error")) { - return NEGOTIATION_ERROR; - } else if (value.equals("malformed-stanza")) { - return MALFORMED_STANZA; - } - - } - return null; - } - - public String toString() { - return getMessage(); - } - - public String getElementName() { - return message; - } - - public String getNamespace() { - return NAMESPACE; - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleTransport.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleTransport.java deleted file mode 100644 index 3586f9a8d..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/JingleTransport.java +++ /dev/null @@ -1,384 +0,0 @@ -package org.jivesoftware.smackx.packet; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smackx.nat.TransportCandidate; - -/** - * A jingle transport extension - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public class JingleTransport implements PacketExtension { - - // static - - public static final String NODENAME = "transport"; - - // non-static - - protected String namespace; - - protected final List candidates = new ArrayList(); - - /** - * Default constructor. - */ - public JingleTransport() { - super(); - } - - /** - * Utility constructor, with a transport candidate element. - * - * @param candidate A transport candidate element to add. - */ - public JingleTransport(final JingleTransportCandidate candidate) { - super(); - addCandidate(candidate); - } - - /** - * Copy constructor. - * - * @param tr the other jingle transport. - */ - public JingleTransport(final JingleTransport tr) { - if (tr != null) { - namespace = tr.namespace; - - if (tr.candidates.size() > 0) { - candidates.addAll(tr.candidates); - } - } - } - - /** - * Adds a transport candidate. - * - * @param candidate the candidate - */ - public void addCandidate(final JingleTransportCandidate candidate) { - if (candidate != null) { - synchronized (candidates) { - candidates.add(candidate); - } - } - } - - /** - * Get an iterator for the candidates - * - * @return an iterator - */ - public Iterator getCandidates() { - return Collections.unmodifiableList(getCandidatesList()).iterator(); - } - - /** - * Get the list of candidates. - * - * @return The candidates list. - */ - public ArrayList getCandidatesList() { - ArrayList res = null; - synchronized (candidates) { - res = new ArrayList(candidates); - } - return res; - } - - /** - * Get the number of transport candidates. - * - * @return The number of transport candidates contained. - */ - public int getCandidatesCount() { - return getCandidatesList().size(); - } - - /** - * Returns the XML element name of the element. - * - * @return the XML element name of the element. - */ - public String getElementName() { - return NODENAME; - } - - /** - * Set the namespace. - * - * @param ns The namespace - */ - protected void setNamespace(final String ns) { - namespace = ns; - } - - /** - * Get the namespace. - * - * @return The namespace - */ - public String getNamespace() { - return namespace; - } - - /** - * Return the XML representation for this element. - */ - public String toXML() { - StringBuffer buf = new StringBuffer(); - - buf.append("<").append(getElementName()).append(" xmlns=\""); - buf.append(getNamespace()).append("\" "); - - synchronized (candidates) { - if (getCandidatesCount() > 0) { - buf.append(">"); - Iterator iter = getCandidates(); - while (iter.hasNext()) { - JingleTransportCandidate candidate = (JingleTransportCandidate) iter - .next(); - buf.append(candidate.toXML()); - } - buf.append("</").append(getElementName()).append(">"); - } else { - buf.append("/>"); - } - } - - return buf.toString(); - } - - /** - * Candidate element in the transport. This class acts as a view of the - * "TransportCandidate" in the Jingle space. - * - * @see TransportCandidate - * @author Alvaro Saurin - */ - public static abstract class JingleTransportCandidate { - - public static final String NODENAME = "candidate"; - - // The transport candidate contained in the element. - protected TransportCandidate transportCandidate; - - /** - * Creates a new JingleTransport child. - */ - public JingleTransportCandidate() { - super(); - } - - /** - * Creates a new JingleTransport child. - * - * @param candidate the media transport candidate - */ - public JingleTransportCandidate(final TransportCandidate candidate) { - super(); - setMediaTransport(candidate); - } - - /** - * Returns the XML element name of the element. - * - * @return the XML element name of the element. - */ - public static String getElementName() { - return NODENAME; - } - - /** - * Get the current transportElement candidate. - * - * @return the transportElement candidate - */ - public TransportCandidate getMediaTransport() { - return transportCandidate; - } - - /** - * Set the transportElement candidate. - * - * @param cand the transportElement candidate - */ - public void setMediaTransport(final TransportCandidate cand) { - if (cand != null) { - transportCandidate = cand; - } - } - - /** - * Get the list of attributes. - * - * @return a string with the list of attributes. - */ - protected String getChildElements() { - return null; - } - - /** - * Obtain a valid XML representation of a trancport candidate - * - * @return A string containing the XML dump of the transport candidate. - */ - public String toXML() { - StringBuffer buf = new StringBuffer(); - String childElements = getChildElements(); - - if (transportCandidate != null && childElements != null) { - buf.append("<").append(getElementName()).append(" "); - buf.append(childElements); - buf.append("/>"); - } - - return buf.toString(); - } - } - - // Subclasses - - /** - * RTP-ICE profile - */ - public static class Ice extends JingleTransport { - public static final String NAMESPACE = "http://jabber.org/protocol/jingle/transport/ice"; - - public Ice() { - super(); - setNamespace(NAMESPACE); - } - - public static class Candidate extends JingleTransportCandidate { - /** - * Default constructor - */ - public Candidate() { - super(); - } - - /** - * Constructor with a transport candidate. - */ - public Candidate(final TransportCandidate tc) { - super(tc); - } - - /** - * Get the elements of this candidate. - */ - protected String getChildElements() { - StringBuffer buf = new StringBuffer(); - - if (transportCandidate != null && transportCandidate instanceof TransportCandidate.Ice) { - TransportCandidate.Ice tci = (TransportCandidate.Ice) transportCandidate; - - // We convert the transportElement candidate to XML here... - buf.append(" generation=\"").append(tci.getGeneration()).append("\""); - buf.append(" ip=\"").append(tci.getIP()).append("\""); - buf.append(" port=\"").append(tci.getPort()).append("\""); - buf.append(" network=\"").append(tci.getNetwork()).append("\""); - buf.append(" username=\"").append(tci.getUsername()).append("\""); - buf.append(" password=\"").append(tci.getPassword()).append("\""); - buf.append(" preference=\"").append(tci.getPreference()).append("\""); - - // Optional elements - if (transportCandidate.getName() != null) { - buf.append(" name=\"").append(tci.getName()).append("\""); - } - } - - return buf.toString(); - } - - } - } - - /** - * Raw UDP profile. - */ - public static class RawUdp extends JingleTransport { - public static final String NAMESPACE = "http://jabber.org/protocol/jingle/transport/raw-udp"; - - public RawUdp() { - super(); - setNamespace(NAMESPACE); - } - - /** - * Add a transport candidate - * - * @see org.jivesoftware.smackx.packet.JingleTransport#addCandidate(org.jivesoftware.smackx.packet.JingleTransport.JingleTransportCandidate) - */ - public void addCandidate(final JingleTransportCandidate candidate) { - candidates.clear(); - super.addCandidate(candidate); - } - - /** - * Get the list of candidates. As a "raw-udp" transport can only contain - * one candidate, we use the first in the list... - * - * @see org.jivesoftware.smackx.packet.JingleTransport#getCandidates() - */ - public ArrayList getCandidatesList() { - ArrayList copy = new ArrayList(); - ArrayList superCandidatesList = super.getCandidatesList(); - - if(superCandidatesList.size() > 0) { - copy.add(superCandidatesList.get(0)); - } - - return copy; - } - - /** - * Raw-udp transport candidate. - */ - public static class Candidate extends JingleTransportCandidate { - /** - * Default constructor - */ - public Candidate() { - super(); - } - - /** - * Constructor with a transport candidate. - */ - public Candidate(final TransportCandidate tc) { - super(tc); - } - - /** - * Get the elements of this candidate. - */ - protected String getChildElements() { - StringBuffer buf = new StringBuffer(); - - if (transportCandidate != null && transportCandidate instanceof TransportCandidate.Fixed) { - TransportCandidate.Fixed tcf = (TransportCandidate.Fixed) transportCandidate; - - buf.append(" generation=\"").append(tcf.getGeneration()).append("\""); - buf.append(" ip=\"").append(tcf.getIP()).append("\""); - buf.append(" port=\"").append(tcf.getPort()).append("\""); - - // Optional parameters - String name = tcf.getName(); - if(name != null) { - buf.append(" name=\"").append(name).append("\""); - } - } - return buf.toString(); - } - - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentDescriptionProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentDescriptionProvider.java deleted file mode 100644 index b47175fc5..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentDescriptionProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -package org.jivesoftware.smackx.provider; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.provider.PacketExtensionProvider; -import org.jivesoftware.smackx.jingle.PayloadType; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleContentDescription.JinglePayloadType; -import org.xmlpull.v1.XmlPullParser; - -/** - * Parser for a Jingle description - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class JingleContentDescriptionProvider implements PacketExtensionProvider { - - /** - * Default constructor - */ - public JingleContentDescriptionProvider() { - super(); - } - - /** - * Parse a iq/jingle/description/payload-type element. - * - * @param parser the input to parse - * @return a payload type element - * @throws Exception - */ - protected JinglePayloadType parsePayload(final XmlPullParser parser) - throws Exception { - int ptId = 0; - String ptName; - int ptChannels = 0; - - try { - ptId = Integer.parseInt(parser.getAttributeValue("", "id")); - } catch (Exception e) { - } - - ptName = parser.getAttributeValue("", "name"); - - try { - ptChannels = Integer.parseInt(parser.getAttributeValue("", "channels")); - } catch (Exception e) { - } - - return new JinglePayloadType(new PayloadType(ptId, ptName, ptChannels)); - } - - /** - * Parse a iq/jingle/description element. - * - * @param parser the input to parse - * @return a description element - * @throws Exception - */ - public PacketExtension parseExtension(final XmlPullParser parser) throws Exception { - boolean done = false; - JingleContentDescription desc = getInstance(); - - while (!done) { - int eventType = parser.next(); - String name = parser.getName(); - - if (eventType == XmlPullParser.START_TAG) { - if (name.equals(JingleContentDescription.JinglePayloadType.NODENAME)) { - desc.addJinglePayloadType(parsePayload(parser)); - } else { - throw new Exception("Unknow element \"" + name + "\" in content."); - } - } else if (eventType == XmlPullParser.END_TAG) { - if (name.equals(JingleContentDescription.NODENAME)) { - done = true; - } - } - } - return desc; - } - - /** - * Return a new instance of this class. Subclasses must overwrite this - * method. - */ - protected abstract JingleContentDescription getInstance(); - - /** - * Jingle audio - */ - public static class Audio extends JingleContentDescriptionProvider { - - /** - * Default constructor - */ - public Audio() { - super(); - } - - /** - * Parse an audio payload type. - */ - public JinglePayloadType parsePayload(final XmlPullParser parser) - throws Exception { - JinglePayloadType pte = super.parsePayload(parser); - PayloadType.Audio pt = new PayloadType.Audio(pte.getPayloadType()); - int ptClockRate = 0; - - try { - ptClockRate = Integer.parseInt(parser.getAttributeValue("", "clockrate")); - } catch (Exception e) { - } - pt.setClockRate(ptClockRate); - - return new JinglePayloadType.Audio(pt); - } - - /** - * Get a new instance of this object. - */ - protected JingleContentDescription getInstance() { - return new JingleContentDescription.Audio(); - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentInfoProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentInfoProvider.java deleted file mode 100644 index 90d0cadb9..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleContentInfoProvider.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.jivesoftware.smackx.provider; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.provider.PacketExtensionProvider; -import org.jivesoftware.smackx.jingle.ContentInfo; -import org.jivesoftware.smackx.packet.JingleContentInfo; -import org.xmlpull.v1.XmlPullParser; - -/** - * Jingle Audio media-info provider - * - * @author Alvaro Saurin - */ -public class JingleContentInfoProvider implements PacketExtensionProvider { - - /** - * Creates a new provider. ProviderManager requires that every - * PacketExtensionProvider has a public, no-argument constructor - */ - public JingleContentInfoProvider() { - super(); - } - - public PacketExtension parseExtension(final XmlPullParser parser) throws Exception { - // This method must be overwritten by subclasses... - return null; - } - - /** - * JingleContentDescription.Audio info provider - */ - public static class Audio extends JingleContentInfoProvider { - - private PacketExtension audioInfo; - - /** - * Empty constructor. - */ - public Audio() { - this(null); - } - - /** - * Constructor with an audio info. - * - * @param audioInfo the media info - */ - public Audio(final PacketExtension audioInfo) { - super(); - this.audioInfo = audioInfo; - } - - /** - * Parse a JingleContentDescription.Audio extension. - */ - public PacketExtension parseExtension(final XmlPullParser parser) - throws Exception { - PacketExtension result = null; - - if (audioInfo != null) { - result = audioInfo; - } else { - String elementName = parser.getName(); - - // Try to get an Audio content info - ContentInfo mi = ContentInfo.Audio.fromString(elementName); - if (mi != null) { - result = new JingleContentInfo.Audio(mi); - } - } - return result; - } - - // Sub-elements - - public static class Busy extends Audio { - public Busy() { - super(new JingleContentInfo.Audio.Busy()); - } - } - - public static class Hold extends Audio { - public Hold() { - super(new JingleContentInfo.Audio.Hold()); - } - } - - public static class Mute extends Audio { - public Mute() { - super(new JingleContentInfo.Audio.Mute()); - } - } - - public static class Queued extends Audio { - public Queued() { - super(new JingleContentInfo.Audio.Queued()); - } - } - - public static class Ringing extends Audio { - public Ringing() { - super(new JingleContentInfo.Audio.Ringing()); - } - } - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProvider.java deleted file mode 100644 index 57d285c72..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProvider.java +++ /dev/null @@ -1,126 +0,0 @@ -/** - * $RCSfile: JingleProvider.java,v $ - * $Revision: 1.1 $ - * $Date: 2006/10/17 19:14:28 $ - * - * 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.provider; - -import org.jivesoftware.smack.XMPPException; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.provider.IQProvider; -import org.jivesoftware.smackx.packet.Jingle; -import org.jivesoftware.smackx.packet.JingleContentDescription; -import org.jivesoftware.smackx.packet.JingleContentInfo; -import org.jivesoftware.smackx.packet.JingleTransport; -import org.xmlpull.v1.XmlPullParser; - -/** - * The JingleProvider parses Jingle packets. - * - * @author Alvaro Saurin - */ -public class JingleProvider implements IQProvider { - - /** - * Creates a new provider. ProviderManager requires that every - * PacketExtensionProvider has a public, no-argument constructor - */ - public JingleProvider() { - super(); - } - - /** - * Parse a iq/jingle element. - */ - public IQ parseIQ(final XmlPullParser parser) throws Exception { - - Jingle jingle = new Jingle(); - String sid = ""; - Jingle.Action action; - String initiator = ""; - String responder = ""; - boolean done = false; - - // Sub-elements providers - JingleContentDescriptionProvider jdpAudio = new JingleContentDescriptionProvider.Audio(); - JingleTransportProvider jtpRawUdp = new JingleTransportProvider.RawUdp(); - JingleTransportProvider jtpIce = new JingleTransportProvider.Ice(); - JingleContentInfoProvider jmipAudio = new JingleContentInfoProvider.Audio(); - - int eventType; - String elementName; - String namespace; - - // Get some attributes for the <jingle> element - sid = parser.getAttributeValue("", "sid"); - action = Jingle.Action.fromString(parser.getAttributeValue("", "action")); - initiator = parser.getAttributeValue("", "initiator"); - responder = parser.getAttributeValue("", "responder"); - - jingle.setSid(sid); - jingle.setAction(action); - jingle.setInitiator(initiator); - jingle.setResponder(responder); - - // Start processing sub-elements - while (!done) { - eventType = parser.next(); - elementName = parser.getName(); - namespace = parser.getNamespace(); - - if (eventType == XmlPullParser.START_TAG) { - - // Parse some well know subelements, depending on the namespaces - // and element names... - - if (elementName.equals(JingleContentDescription.NODENAME) - && namespace.equals(JingleContentDescription.Audio.NAMESPACE)) { - jingle.addDescription((JingleContentDescription) jdpAudio - .parseExtension(parser)); - } else if (elementName.equals(JingleTransport.NODENAME)) { - - // Parse the possible transport namespaces - if (namespace.equals(JingleTransport.RawUdp.NAMESPACE)) { - jingle.addTransport((JingleTransport) jtpRawUdp - .parseExtension(parser)); - } else if (namespace.equals(JingleTransport.Ice.NAMESPACE)) { - jingle.addTransport((JingleTransport) jtpIce - .parseExtension(parser)); - } else { - throw new XMPPException("Unknown transport namespace \"" - + namespace + "\" in Jingle packet."); - } - } else if (namespace.equals(JingleContentInfo.Audio.NAMESPACE)) { - jingle.setContentInfo((JingleContentInfo) jmipAudio - .parseExtension(parser)); - } else { - throw new XMPPException("Unknown combination of namespace \"" - + namespace + "\" and element name \"" + elementName - + "\" in Jingle packet."); - } - - } else if (eventType == XmlPullParser.END_TAG) { - if (parser.getName().equals(Jingle.getElementName())) { - done = true; - } - } - } - - return jingle; - } -} diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProviderTest.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProviderTest.java deleted file mode 100644 index bbbc0a340..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleProviderTest.java +++ /dev/null @@ -1,117 +0,0 @@ -package org.jivesoftware.smackx.provider; - -import org.jivesoftware.smack.PacketCollector; -import org.jivesoftware.smack.SmackConfiguration; -import org.jivesoftware.smack.filter.PacketFilter; -import org.jivesoftware.smack.filter.PacketTypeFilter; -import org.jivesoftware.smack.packet.IQ; -import org.jivesoftware.smack.provider.IQProvider; -import org.jivesoftware.smack.provider.ProviderManager; -import org.jivesoftware.smack.test.SmackTestCase; -import org.jivesoftware.smackx.packet.Jingle; - -public class JingleProviderTest extends SmackTestCase { - - public JingleProviderTest(final String name) { - super(name); - } - - public void testProviderManager() { - IQProvider iqProv; - String elementNamee = Jingle.getElementName(); - String nameSpace = Jingle.getNamespace(); - - System.out.println("Testing if the Jingle IQ provider is registered..."); - - // Verify that the Jingle IQProvider is registered. - iqProv = (IQProvider)ProviderManager.getIQProvider(elementNamee, nameSpace); - - assertNotNull(iqProv); - } - - /** - * Test for parsing a Jingle - */ - public void testParseIQSimple() { - - // Create a dummy packet for testing... - IQfake iqSent = new IQfake ( - " <jingle xmlns='http://jabber.org/protocol/jingle'" + - " initiator=\"gorrino@viejo.com\"" + - " responder=\"colico@hepatico.com\"" + - " action=\"transport-info\" sid=\"\">" + - " <description xmlns='http://jabber.org/protocol/jingle/content/audio'>" + - " <payload-type id=\"34\" name=\"supercodec-34\"/>" + - " <payload-type id=\"23\" name=\"supercodec-23\"/>" + - " </description>" + - " <transport xmlns='http://jabber.org/protocol/jingle/transport/ice'>" + - " <candidate generation=\"1\"" + - " ip=\"192.168.1.1\"" + - " password=\"secret\"" + - " port=\"8080\"" + - " username=\"username\"" + - " preference=\"1\"/>" + - " </transport>" + - "</jingle>"); - - iqSent.setTo(getFullJID(0)); - iqSent.setFrom(getFullJID(0)); - iqSent.setType(IQ.Type.GET); - - // Create a filter and a collector... - PacketFilter filter = new PacketTypeFilter(IQ.class); - PacketCollector collector = getConnection(0).createPacketCollector(filter); - - System.out.println("Testing if a Jingle IQ can be sent and received..."); - - // Send the iq packet with an invalid namespace - getConnection(0).sendPacket(iqSent); - - // Receive the packet - IQ iqReceived = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout()); - - // Stop queuing results - collector.cancel(); - - if (iqReceived == null) { - fail("No response from server"); - } - else if (iqReceived.getType() == IQ.Type.ERROR) { - fail("The server did reply with an error packet: " + iqReceived.getError().getCode()); - } - else { - assertTrue(iqReceived instanceof Jingle); - - Jingle jin = (Jingle) iqReceived; - - System.out.println("Sent: " + iqSent.toXML()); - System.out.println("Received: " + jin.toXML()); - } - } - - /** - * Simple class for testing an IQ... - * @author Alvaro Saurin - */ - private class IQfake extends IQ { - private String s; - - public IQfake(final String s) { - super(); - this.s = s; - } - - public String getChildElementXML() { - StringBuffer buf = new StringBuffer(); - buf.append(s); - return buf.toString(); - } - } - - - protected int getMaxConnections() { - return 2; - } - -} - diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleTransportProvider.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleTransportProvider.java deleted file mode 100644 index 7af2edba4..000000000 --- a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/provider/JingleTransportProvider.java +++ /dev/null @@ -1,226 +0,0 @@ -package org.jivesoftware.smackx.provider; - -import org.jivesoftware.smack.packet.PacketExtension; -import org.jivesoftware.smack.provider.PacketExtensionProvider; -import org.jivesoftware.smackx.nat.TransportCandidate; -import org.jivesoftware.smackx.packet.JingleTransport; -import org.jivesoftware.smackx.packet.JingleTransport.JingleTransportCandidate; -import org.xmlpull.v1.XmlPullParser; - -/** - * Provider for a Jingle transport element - * - * @author Alvaro Saurin <alvaro.saurin@gmail.com> - */ -public abstract class JingleTransportProvider implements PacketExtensionProvider { - - /** - * Creates a new provider. ProviderManager requires that every - * PacketExtensionProvider has a public, no-argument constructor - */ - public JingleTransportProvider() { - super(); - } - - /** - * Obtain the corresponding JingleTransport instance. - * - * @return a new JingleTransport instance - */ - protected JingleTransport getInstance() { - return new JingleTransport(); - } - - /** - * Parse a iq/jingle/transport element. - * - * @param parser the structure to parse - * @return a transport element. - * @throws Exception - */ - public PacketExtension parseExtension(final XmlPullParser parser) throws Exception { - boolean done = false; - JingleTransport trans = getInstance(); - - while (!done) { - int eventType = parser.next(); - String name = parser.getName(); - - if (eventType == XmlPullParser.START_TAG) { - if (name.equals(JingleTransportCandidate.NODENAME)) { - trans.addCandidate(parseCandidate(parser)); - } else { - throw new Exception("Unknown tag \"" + name + "\" in transport element."); - } - } else if (eventType == XmlPullParser.END_TAG) { - if (name.equals(JingleTransport.NODENAME)) { - done = true; - } - } - } - - return trans; - } - - protected abstract JingleTransportCandidate parseCandidate(final XmlPullParser parser) - throws Exception; - - /** - * RTP-ICE profile - */ - public static class Ice extends JingleTransportProvider { - - /** - * Defauls constructor. - */ - public Ice() { - super(); - } - - /** - * Obtain the corresponding JingleTransport.Ice instance. - * - * @return a new JingleTransport.Ice instance - */ - protected JingleTransport getInstance() { - return new JingleTransport.Ice(); - } - - /** - * Parse a iq/jingle/transport/candidate element. - * - * @param parser the structure to parse - * @return a candidate element - * @throws Exception - */ - protected JingleTransportCandidate parseCandidate(XmlPullParser parser) throws Exception { - TransportCandidate.Ice mt = new TransportCandidate.Ice(); - - String channel = parser.getAttributeValue("", "channel"); - String generation = parser.getAttributeValue("", "generation"); - String ip = parser.getAttributeValue("", "ip"); - String name = parser.getAttributeValue("", "name"); - String network = parser.getAttributeValue("", "network"); - String username = parser.getAttributeValue("", "username"); - String password = parser.getAttributeValue("", "password"); - String port = parser.getAttributeValue("", "port"); - String preference = parser.getAttributeValue("", "preference"); - String proto = parser.getAttributeValue("", "proto"); - - if (channel != null) { - mt.setChannel(new TransportCandidate.Channel(channel)); - } - - if (generation != null) { - try { - mt.setGeneration(Integer.parseInt(generation)); - } catch (Exception e) { - } - } - - if (ip != null) { - mt.setIP(ip); - } - - if (name != null) { - mt.setName(name); - } - - if (network != null) { - try { - mt.setNetwork(Integer.parseInt(network)); - } catch (Exception e) { - } - } - - if (username != null) { - mt.setUsername(username); - } - - if (password != null) { - mt.setPassword(password); - } - - if (port != null) { - try { - mt.setPort(Integer.parseInt(port)); - } catch (Exception e) { - } - } - - if (preference != null) { - try { - mt.setPreference(Integer.parseInt(preference)); - } catch (Exception e) { - } - } - - if (proto != null) { - mt.setProto(new TransportCandidate.Protocol(proto)); - } - - return new JingleTransport.Ice.Candidate(mt); - } - } - - /** - * Raw UDP profile - */ - public static class RawUdp extends JingleTransportProvider { - - /** - * Defauls constructor. - */ - public RawUdp() { - super(); - } - - /** - * Obtain the corresponding JingleTransport.RawUdp instance. - * - * @return a new JingleTransport.RawUdp instance - */ - protected JingleTransport getInstance() { - return new JingleTransport.RawUdp(); - } - - /** - * Parse a iq/jingle/transport/candidate element. - * - * @param parser the structure to parse - * @return a candidate element - * @throws Exception - */ - protected JingleTransportCandidate parseCandidate(XmlPullParser parser) throws Exception { - TransportCandidate.Fixed mt = new TransportCandidate.Fixed(); - - String generation = parser.getAttributeValue("", "generation"); - String ip = parser.getAttributeValue("", "ip"); - String name = parser.getAttributeValue("", "name"); - String port = parser.getAttributeValue("", "port"); - - if (generation != null) { - try { - mt.setGeneration(Integer.parseInt(generation)); - } catch (Exception e) { - } - } - - if (ip != null) { - mt.setIP(ip); - } - - if (name != null) { - mt.setName(name); - } - - if (port != null) { - try { - mt.setPort(Integer.parseInt(port)); - } catch (Exception e) { - } - } - return new JingleTransport.RawUdp.Candidate(mt); - } - } -} |