1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-11 01:59:38 +02:00

"not connected" is now a checked Exception thrown by sendPacket()

There is a unsolveable race condition between the connection state and
sendPacket(), i.e. the connection could go down, right after the
method calling sendPacket is called, but before sendPacket() is
invoked. Before this change, sendPacket() has thrown an unchecked
IllegalStateException, which could be ignored by the Smack user, who
would also not notice the race condition. We have decided to throw a
checked Exception in this case now, to make the Smack user aware of
this situation.

SMACK-426
This commit is contained in:
Florian Schmaus 2014-03-19 14:22:20 +01:00
parent d8c656270e
commit fcc8414a92
101 changed files with 845 additions and 382 deletions

View file

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.jingle.listeners.JingleListener;
@ -254,7 +255,7 @@ public class ContentNegotiator extends JingleNegotiator {
return result;
}
public void triggerContentEstablished() {
public void triggerContentEstablished() throws NotConnectedException {
PayloadType bestCommonAudioPt = getMediaNegotiator().getBestCommonAudioPt();
TransportCandidate bestRemoteCandidate = getTransportNegotiator().getBestRemoteCandidate();
@ -266,8 +267,9 @@ public class ContentNegotiator extends JingleNegotiator {
/**
* Trigger a session established event.
* @throws NotConnectedException
*/
private void triggerContentEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc) {
private void triggerContentEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc) throws NotConnectedException {
// Let the session know that we've established a content/media segment.
JingleSession session = getSession();

View file

@ -235,7 +235,7 @@ public class JingleManager implements JingleSessionListener {
if (aux != null)
try {
aux.terminate();
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
@ -478,7 +478,7 @@ public class JingleManager implements JingleSessionListener {
for (JingleSession jingleSession : sessions)
try {
jingleSession.terminate();
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -27,6 +27,7 @@ import org.jivesoftware.smack.AbstractConnectionListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketFilter;
@ -397,7 +398,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
// Send section
// ----------------------------------------------------------------------------------------------------------
public void sendPacket(IQ iq) {
public void sendPacket(IQ iq) throws NotConnectedException {
if (iq instanceof Jingle) {
@ -415,8 +416,9 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
*
* @param jout
* the Jingle packet we want to complete and send
* @throws NotConnectedException
*/
public Jingle sendFormattedJingle(Jingle jout) {
public Jingle sendFormattedJingle(Jingle jout) throws NotConnectedException {
return sendFormattedJingle(null, jout);
}
@ -429,8 +431,9 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
* The Jingle packet we are responing to
* @param jout
* the Jingle packet we want to complete and send
* @throws NotConnectedException
*/
public Jingle sendFormattedJingle(IQ iq, Jingle jout) {
public Jingle sendFormattedJingle(IQ iq, Jingle jout) throws NotConnectedException {
if (jout != null) {
if (jout.getInitiator() == null) {
jout.setInitiator(getInitiator());
@ -798,7 +801,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
public void mediaClosed(PayloadType cand) {
}
public void mediaEstablished(PayloadType pt) {
public void mediaEstablished(PayloadType pt) throws NotConnectedException {
if (isFullyEstablished()) {
Jingle jout = new Jingle(JingleActionEnum.SESSION_ACCEPT);
@ -819,7 +822,7 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
JingleTransportListener jingleTransportListener = new JingleTransportListener() {
public void transportEstablished(TransportCandidate local, TransportCandidate remote) {
public void transportEstablished(TransportCandidate local, TransportCandidate remote) throws NotConnectedException {
if (isFullyEstablished()) {
// Indicate that this session is active.
@ -959,8 +962,9 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
* Terminates the session with default reason.
*
* @throws XMPPException
* @throws NotConnectedException
*/
public void terminate() throws XMPPException {
public void terminate() throws XMPPException, NotConnectedException {
terminate("Closed Locally");
}
@ -968,8 +972,9 @@ public class JingleSession extends JingleNegotiator implements MediaReceivedList
* Terminates the session with a custom reason.
*
* @throws XMPPException
* @throws NotConnectedException
*/
public void terminate(String reason) throws XMPPException {
public void terminate(String reason) throws XMPPException, NotConnectedException {
if (isClosed())
return;
LOGGER.fine("Terminate " + reason);

View file

@ -134,8 +134,8 @@ public class JingleSessionRequest {
//session.sendAck(this.getJingle());
session.updatePacketListener();
session.terminate("Declined");
} catch (XMPPException e) {
LOGGER.log(Level.SEVERE, "XMPPexception in reject", e);
} catch (Exception e) {
LOGGER.log(Level.SEVERE, "Exception in reject", e);
}
}
}

View file

@ -16,7 +16,6 @@
*/
package org.jivesoftware.smackx.jingle;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.jingle.packet.Jingle;
import org.jivesoftware.smackx.jingle.packet.JingleError;
@ -98,7 +97,7 @@ public class JingleSessionStateActive extends JingleSessionState {
try {
session.terminate("Closed remotely");
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -16,7 +16,6 @@
*/
package org.jivesoftware.smackx.jingle;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.jingle.packet.Jingle;
@ -124,7 +123,7 @@ public class JingleSessionStatePending extends JingleSessionState {
try {
session.terminate("Closed remotely");
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -203,7 +203,7 @@ public class JingleSessionStateUnknown extends JingleSessionState {
try {
session.terminate("Closed remotely");
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.jingle.listeners;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smackx.jingle.media.PayloadType;
/**
@ -28,8 +29,9 @@ public interface JingleMediaListener extends JingleListener {
* Notification that the jmf has been negotiated and established.
*
* @param pt The payload type agreed.
* @throws NotConnectedException
*/
public void mediaEstablished(PayloadType pt);
public void mediaEstablished(PayloadType pt) throws NotConnectedException;
/**
* Notification that a payload type must be cancelled

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.listeners;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.jivesoftware.smackx.jingle.media.PayloadType;
@ -35,9 +36,10 @@ public interface JingleSessionListener extends JingleListener {
* service.
* @param localCandidate the local candidate where we must listen for connections
* @param jingleSession Session that called the method
* @throws NotConnectedException
*/
public void sessionEstablished(PayloadType pt, TransportCandidate remoteCandidate,
TransportCandidate localCandidate, JingleSession jingleSession);
TransportCandidate localCandidate, JingleSession jingleSession) throws NotConnectedException;
/**
* Notification that the session was declined.

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.listeners;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.nat.TransportCandidate;
@ -33,9 +34,10 @@ public interface JingleTransportListener extends JingleListener {
* in the local machine
* @param remote The transport candidate that has been used for
* transmitting to the remote machine
* @throws NotConnectedException
*/
public void transportEstablished(TransportCandidate local,
TransportCandidate remote);
TransportCandidate remote) throws NotConnectedException;
/**
* Notification that a transport must be cancelled.

View file

@ -20,6 +20,7 @@ import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.jingle.ContentNegotiator;
@ -101,8 +102,9 @@ public class MediaNegotiator extends JingleNegotiator {
* the packet received
* @return the new Jingle packet to send.
* @throws XMPPException
* @throws NotConnectedException
*/
public List<IQ> dispatchIncomingPacket(IQ iq, String id) throws XMPPException {
public List<IQ> dispatchIncomingPacket(IQ iq, String id) throws XMPPException, NotConnectedException {
List<IQ> responses = new ArrayList<IQ>();
IQ response = null;
@ -199,8 +201,9 @@ public class MediaNegotiator extends JingleNegotiator {
*
* @param jingle
* @return the iq
* @throws NotConnectedException
*/
private IQ receiveContentAcceptAction(Jingle jingle, JingleDescription description) throws XMPPException {
private IQ receiveContentAcceptAction(Jingle jingle, JingleDescription description) throws XMPPException, NotConnectedException {
IQ response = null;
List<PayloadType> offeredPayloads = new ArrayList<PayloadType>();
@ -473,8 +476,9 @@ public class MediaNegotiator extends JingleNegotiator {
*
* @param bestPt
* payload type that has been agreed.
* @throws NotConnectedException
*/
protected void triggerMediaEstablished(PayloadType bestPt) {
protected void triggerMediaEstablished(PayloadType bestPt) throws NotConnectedException {
List<JingleListener> listeners = getListenersList();
for (JingleListener li : listeners) {
if (li instanceof JingleMediaListener) {

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
@ -43,8 +44,9 @@ public class BasicResolver extends TransportResolver {
* <p/>
* The BasicResolver takes the IP addresses of the interfaces and uses the
* first non-loopback, non-linklocal and non-sitelocal address.
* @throws NotConnectedException
*/
public synchronized void resolve(JingleSession session) throws XMPPException {
public synchronized void resolve(JingleSession session) throws XMPPException, NotConnectedException {
setResolveInit();

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
@ -58,8 +59,9 @@ public class BridgedResolver extends TransportResolver {
* Resolve Bridged Candidate.
* <p/>
* The BridgedResolver takes the IP addresse and ports of a jmf proxy service.
* @throws NotConnectedException
*/
public synchronized void resolve(JingleSession session) throws XMPPException {
public synchronized void resolve(JingleSession session) throws XMPPException, NotConnectedException {
setResolveInit();

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
@ -52,7 +53,7 @@ public class BridgedTransportManager extends JingleTransportManager implements J
// Implement a Session Listener to relay candidates after establishment
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) throws NotConnectedException {
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);
}

View file

@ -16,6 +16,7 @@
*/
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
@ -50,8 +51,9 @@ public class FixedResolver extends TransportResolver {
/**
* Resolve the IP address.
* @throws NotConnectedException
*/
public synchronized void resolve(JingleSession session) throws XMPPException {
public synchronized void resolve(JingleSession session) throws XMPPException, NotConnectedException {
if (!isResolving()) {
setResolveInit();

View file

@ -17,6 +17,7 @@
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
@ -50,7 +51,7 @@ public class ICETransportManager extends JingleTransportManager implements Jingl
// Implement a Session Listener to relay candidates after establishment
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) {
public void sessionEstablished(PayloadType pt, TransportCandidate rc, TransportCandidate lc, JingleSession jingleSession) throws NotConnectedException {
if (lc instanceof ICECandidate) {
if (((ICECandidate) lc).getType().equals("relay")) {
RTPBridge rtpBridge = RTPBridge.relaySession(lc.getConnection(), lc.getSessionId(), lc.getPassword(), rc, lc);

View file

@ -25,6 +25,7 @@ import java.util.Iterator;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
@ -383,8 +384,9 @@ public class RTPBridge extends IQ {
* @param connection
* @param sessionID
* @return the new RTPBridge
* @throws NotConnectedException
*/
public static RTPBridge getRTPBridge(XMPPConnection connection, String sessionID) {
public static RTPBridge getRTPBridge(XMPPConnection connection, String sessionID) throws NotConnectedException {
if (!connection.isConnected()) {
return null;
@ -410,9 +412,10 @@ public class RTPBridge extends IQ {
* @return true if the server supports the RTPBridge service
* @throws XMPPErrorException
* @throws NoResponseException
* @throws NotConnectedException
*/
public static boolean serviceAvailable(XMPPConnection connection) throws NoResponseException,
XMPPErrorException {
XMPPErrorException, NotConnectedException {
if (!connection.isConnected()) {
return false;
@ -448,8 +451,9 @@ public class RTPBridge extends IQ {
*
* @param connection
* @return the RTPBridge
* @throws NotConnectedException
*/
public static RTPBridge relaySession(XMPPConnection connection, String sessionID, String pass, TransportCandidate proxyCandidate, TransportCandidate localCandidate) {
public static RTPBridge relaySession(XMPPConnection connection, String sessionID, String pass, TransportCandidate proxyCandidate, TransportCandidate localCandidate) throws NotConnectedException {
if (!connection.isConnected()) {
return null;
@ -482,8 +486,9 @@ public class RTPBridge extends IQ {
*
* @param xmppConnection
* @return public IP String or null if not found
* @throws NotConnectedException
*/
public static String getPublicIP(XMPPConnection xmppConnection) {
public static String getPublicIP(XMPPConnection xmppConnection) throws NotConnectedException {
if (!xmppConnection.isConnected()) {
return null;

View file

@ -22,6 +22,7 @@ import java.util.List;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.XMPPException;
@ -181,8 +182,9 @@ public class STUN extends IQ {
*
* @param connection
* @return the STUN server address
* @throws NotConnectedException
*/
public static STUN getSTUNServer(XMPPConnection connection) {
public static STUN getSTUNServer(XMPPConnection connection) throws NotConnectedException {
if (!connection.isConnected()) {
return null;

View file

@ -26,6 +26,7 @@ import java.util.Enumeration;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
import org.xmlpull.v1.XmlPullParserFactory;
@ -262,8 +263,9 @@ public class STUNResolver extends TransportResolver {
/**
* Resolve the IP and obtain a valid transport method.
* @throws NotConnectedException
*/
public synchronized void resolve(JingleSession session) throws XMPPException {
public synchronized void resolve(JingleSession session) throws XMPPException, NotConnectedException {
setResolveInit();

View file

@ -16,7 +16,6 @@
*/
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
/**
@ -40,7 +39,7 @@ public class STUNTransportManager extends JingleTransportManager {
protected TransportResolver createResolver(JingleSession session) {
try {
stunResolver.resolve(session);
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}
return stunResolver;

View file

@ -24,6 +24,7 @@ import java.util.List;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.jingle.ContentNegotiator;
@ -319,12 +320,22 @@ public abstract class TransportNegotiator extends JingleNegotiator {
jout.addContent(content);
// Send the packet
js.sendFormattedJingle(jin, jout);
try {
js.sendFormattedJingle(jin, jout);
}
catch (NotConnectedException e) {
throw new IllegalStateException(e);
}
acceptedRemoteCandidates.add(bestRemote);
}
if ((isEstablished()) && (getNegotiatorState() == JingleNegotiatorState.PENDING)) {
setNegotiatorState(JingleNegotiatorState.SUCCEEDED);
triggerTransportEstablished(getAcceptedLocalCandidate(), bestRemote);
try {
triggerTransportEstablished(getAcceptedLocalCandidate(), bestRemote);
}
catch (NotConnectedException e) {
throw new IllegalStateException(e);
}
break;
}
}
@ -400,7 +411,12 @@ public abstract class TransportNegotiator extends JingleNegotiator {
jout.addContent(content);
// Send the packet
js.sendFormattedJingle(jin, jout);
try {
js.sendFormattedJingle(jin, jout);
}
catch (NotConnectedException e) {
throw new IllegalStateException(e);
}
acceptedRemoteCandidates.add(bestRemote);
}
if (isEstablished()) {
@ -414,7 +430,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
try {
session
.terminate("Unable to negotiate session. This may be caused by firewall configuration problems.");
} catch (XMPPException e) {
} catch (Exception e) {
e.printStackTrace();
}
}
@ -508,8 +524,9 @@ public abstract class TransportNegotiator extends JingleNegotiator {
* Send an offer for a transport candidate
*
* @param cand
* @throws NotConnectedException
*/
private synchronized void sendTransportCandidateOffer(TransportCandidate cand) {
private synchronized void sendTransportCandidateOffer(TransportCandidate cand) throws NotConnectedException {
if (!cand.isNull()) {
// Offer our new candidate...
addOfferedCandidate(cand);
@ -545,7 +562,7 @@ public abstract class TransportNegotiator extends JingleNegotiator {
if (resolverListener == null) {
// Add a listener that sends the offer when the resolver finishes...
resolverListener = new TransportResolverListener.Resolver() {
public void candidateAdded(TransportCandidate cand) {
public void candidateAdded(TransportCandidate cand) throws NotConnectedException {
sendTransportCandidateOffer(cand);
}
@ -763,8 +780,9 @@ public abstract class TransportNegotiator extends JingleNegotiator {
*
* @param local TransportCandidate that has been agreed.
* @param remote TransportCandidate that has been agreed.
* @throws NotConnectedException
*/
private void triggerTransportEstablished(TransportCandidate local, TransportCandidate remote) {
private void triggerTransportEstablished(TransportCandidate local, TransportCandidate remote) throws NotConnectedException {
List<JingleListener> listeners = getListenersList();
for (JingleListener li : listeners) {
if (li instanceof JingleTransportListener) {

View file

@ -25,6 +25,7 @@ import java.util.List;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.SmackException.NotConnectedException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.jingle.JingleSession;
@ -208,8 +209,9 @@ public abstract class TransportResolver {
* Trigger a new candidate added event.
*
* @param cand The candidate added to the list of candidates.
* @throws NotConnectedException
*/
protected void triggerCandidateAdded(TransportCandidate cand) {
protected void triggerCandidateAdded(TransportCandidate cand) throws NotConnectedException {
Iterator<TransportResolverListener> iter = getListenersList().iterator();
while (iter.hasNext()) {
TransportResolverListener trl = iter.next();
@ -264,8 +266,9 @@ public abstract class TransportResolver {
* Add a new transport candidate
*
* @param cand The candidate to add
* @throws NotConnectedException
*/
protected void addCandidate(TransportCandidate cand) {
protected void addCandidate(TransportCandidate cand) throws NotConnectedException {
synchronized (candidates) {
if (!candidates.contains(cand))
candidates.add(cand);

View file

@ -16,6 +16,8 @@
*/
package org.jivesoftware.smackx.jingle.nat;
import org.jivesoftware.smack.SmackException.NotConnectedException;
/**
* Transport resolver Interface
*/
@ -33,8 +35,9 @@ public abstract interface TransportResolverListener {
* A transport candidate has been added
*
* @param cand The transport candidate.
* @throws NotConnectedException
*/
public void candidateAdded(TransportCandidate cand);
public void candidateAdded(TransportCandidate cand) throws NotConnectedException;
/**
* All the transport candidates have been obtained.