mirror of
https://github.com/vanitasvitae/Smack.git
synced 2024-09-27 18:19:33 +02:00
a616e34bd7
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@7364 b35dd754-fafc-0310-a699-88a17e54d16e
379 lines
8.8 KiB
Java
379 lines
8.8 KiB
Java
/**
|
|
* $RCSfile$
|
|
* $Revision: 7329 $
|
|
* $Date: 2007-02-28 20:59:28 -0300 (qua, 28 fev 2007) $
|
|
*
|
|
* Copyright 2003-2005 Jive Software.
|
|
*
|
|
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
package org.jivesoftware.smackx.jingle;
|
|
|
|
import org.jivesoftware.smack.XMPPConnection;
|
|
import org.jivesoftware.smack.XMPPException;
|
|
import org.jivesoftware.smack.packet.IQ;
|
|
import org.jivesoftware.smackx.jingle.listeners.JingleListener;
|
|
import org.jivesoftware.smackx.packet.Jingle;
|
|
import org.jivesoftware.smackx.packet.JingleError;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
/**
|
|
* Basic Jingle negotiator.
|
|
* <p/>
|
|
* </p>
|
|
* <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/>
|
|
* </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(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(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 newState the state to set
|
|
* @throws XMPPException
|
|
*/
|
|
protected void setState(State newState) {
|
|
boolean transition = newState != state;
|
|
|
|
if (transition && state != null) {
|
|
state.eventExit();
|
|
}
|
|
|
|
state = newState;
|
|
|
|
if (transition && state != null) {
|
|
state.eventEnter();
|
|
}
|
|
}
|
|
|
|
// Acks management
|
|
|
|
/**
|
|
* Add expected ID
|
|
*
|
|
* @param id
|
|
*/
|
|
public void addExpectedId(String id) {
|
|
expectedAckId = id;
|
|
}
|
|
|
|
/**
|
|
* Check if the passed ID is the expected ID
|
|
*
|
|
* @param id
|
|
* @return
|
|
*/
|
|
public boolean isExpectedId(String id) {
|
|
if (id != null) {
|
|
return id.equals(expectedAckId);
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove and expected ID
|
|
*
|
|
* @param id
|
|
*/
|
|
public void removeExpectedId(String id) {
|
|
addExpectedId((String) null);
|
|
}
|
|
|
|
// Listeners
|
|
|
|
/**
|
|
* Add a Jingle session listener to listen to incoming session requests.
|
|
*
|
|
* @param li The listener
|
|
* @see org.jivesoftware.smackx.jingle.listeners.JingleListener
|
|
*/
|
|
public void addListener(JingleListener li) {
|
|
synchronized (listeners) {
|
|
listeners.add(li);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Removes a Jingle session listener.
|
|
*
|
|
* @param li The jingle session listener to be removed
|
|
* @see org.jivesoftware.smackx.jingle.listeners.JingleListener
|
|
*/
|
|
public void removeListener(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(IQ iq, 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 msg The message.
|
|
*/
|
|
public JingleException(String msg) {
|
|
super(msg);
|
|
error = null;
|
|
}
|
|
|
|
/**
|
|
* Constructor with an error response.
|
|
*
|
|
* @param error The error message.
|
|
*/
|
|
public JingleException(JingleError error) {
|
|
super();
|
|
this.error = error;
|
|
}
|
|
|
|
/**
|
|
* Return the error message.
|
|
*
|
|
* @return the error
|
|
*/
|
|
public JingleError getError() {
|
|
return error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Negotiation state and events.
|
|
* <p/>
|
|
* </p>
|
|
* <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(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(JingleNegotiator neg) {
|
|
this.neg = neg;
|
|
}
|
|
|
|
// State transition events
|
|
|
|
public Jingle eventAck(IQ iq) throws XMPPException {
|
|
// We have received an Ack
|
|
return null;
|
|
}
|
|
|
|
public void eventError(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(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventAccept(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventRedirect(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventModify(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventDecline(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventInfo(Jingle jin) throws XMPPException {
|
|
return null;
|
|
}
|
|
|
|
public Jingle eventTerminate(Jingle jin) throws XMPPException {
|
|
if (neg != null && !neg.invalidState()) {
|
|
neg.close();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public void eventEnter() {
|
|
}
|
|
|
|
public void eventExit() {
|
|
if (neg != null) {
|
|
neg.removeExpectedId(null);
|
|
}
|
|
}
|
|
}
|
|
}
|