1) SOCKS5 listening thread and socket should now be closed properly. SMACK-148

2) PacketCollectors are now properly timed-out.

git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/trunk@4260 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
Alex Wenckus 2006-07-05 17:45:59 +00:00 committed by alex
parent 0bc5b7b404
commit 58254d82aa
1 changed files with 93 additions and 56 deletions

View File

@ -100,8 +100,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
/* /*
* (non-Javadoc) * (non-Javadoc)
* *
* @see org.jivesoftware.smackx.filetransfer.StreamNegotiator#initiateDownload(org.jivesoftware.smackx.packet.StreamInitiation, * @see org.jivesoftware.smackx.filetransfer.StreamNegotiator#initiateDownload(
* java.io.File) * org.jivesoftware.smackx.packet.StreamInitiation, java.io.File)
*/ */
InputStream negotiateIncomingStream(Packet streamInitiation) InputStream negotiateIncomingStream(Packet streamInitiation)
throws XMPPException { throws XMPPException {
@ -174,7 +174,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
* @throws XMPPException * @throws XMPPException
*/ */
private SelectedHostInfo selectHost(Bytestream streamHostsInfo) private SelectedHostInfo selectHost(Bytestream streamHostsInfo)
throws XMPPException { throws XMPPException
{
Iterator it = streamHostsInfo.getStreamHosts().iterator(); Iterator it = streamHostsInfo.getStreamHosts().iterator();
StreamHost selectedHost = null; StreamHost selectedHost = null;
Socket socket = null; Socket socket = null;
@ -196,7 +197,7 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
socket = null; socket = null;
} }
} }
if (selectedHost == null || socket == null) { if (selectedHost == null || socket == null || !socket.isConnected()) {
throw new XMPPException( throw new XMPPException(
"Could not establish socket with any provided host", new XMPPError(406)); "Could not establish socket with any provided host", new XMPPError(406));
} }
@ -230,7 +231,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
* org.jivesoftware.smackx.packet.StreamInitiation, java.io.File) * org.jivesoftware.smackx.packet.StreamInitiation, java.io.File)
*/ */
public OutputStream createOutgoingStream(String streamID, String initiator, public OutputStream createOutgoingStream(String streamID, String initiator,
String target) throws XMPPException { String target) throws XMPPException
{
Socket socket; Socket socket;
try { try {
socket = initBytestreamSocket(streamID, initiator, target); socket = initBytestreamSocket(streamID, initiator, target);
@ -241,7 +243,7 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
if (socket != null) { if (socket != null) {
try { try {
return socket.getOutputStream(); return new BufferedOutputStream(socket.getOutputStream());
} }
catch (IOException e) { catch (IOException e) {
throw new XMPPException("Error establishing output stream", e); throw new XMPPException("Error establishing output stream", e);
@ -251,7 +253,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
} }
private Socket initBytestreamSocket(final String sessionID, private Socket initBytestreamSocket(final String sessionID,
String initiator, String target) throws Exception { String initiator, String target) throws Exception
{
ProxyProcess process; ProxyProcess process;
try { try {
process = establishListeningSocket(); process = establishListeningSocket();
@ -294,7 +297,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
*/ */
private SelectedHostInfo waitForUsedHostResponse(String sessionID, private SelectedHostInfo waitForUsedHostResponse(String sessionID,
final ProxyProcess proxy, final String digest, final ProxyProcess proxy, final String digest,
final Bytestream query) throws XMPPException, IOException { final Bytestream query) throws XMPPException, IOException
{
SelectedHostInfo info = new SelectedHostInfo(); SelectedHostInfo info = new SelectedHostInfo();
PacketCollector collector = connection PacketCollector collector = connection
@ -340,7 +344,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
activate.getPacketID())); activate.getPacketID()));
connection.sendPacket(activate); connection.sendPacket(activate);
IQ serverResponse = (IQ) collector.nextResult(); IQ serverResponse = (IQ) collector.nextResult(SmackConfiguration
.getPacketReplyTimeout());
collector.cancel(); collector.cancel();
if (!serverResponse.getType().equals(IQ.Type.RESULT)) { if (!serverResponse.getType().equals(IQ.Type.RESULT)) {
info.establishedSocket.close(); info.establishedSocket.close();
@ -395,12 +400,12 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
* </iq> * </iq>
* </pre> * </pre>
* *
* @param from initiator@host1/foo - The file transfer initiator. * @param from initiator@host1/foo - the file transfer initiator.
* @param to target@host2/bar - The file transfer target. * @param to target@host2/bar - the file transfer target.
* @param sid 'mySID' - the unique identifier for this file transfer * @param sid 'mySID' - the unique identifier for this file transfer
* @param localIP The IP of the local machine if it is being provided, null otherwise. * @param localIP the IP of the local machine if it is being provided, null otherwise.
* @param port The port of the local mahine if it is being provided, null otherwise. * @param port the port of the local mahine if it is being provided, null otherwise.
* @return Returns the created <b><i>Bytestream</b></i> packet * @return the created <b><i>Bytestream</b></i> packet
*/ */
private Bytestream createByteStreamInit(final String from, final String to, private Bytestream createByteStreamInit(final String from, final String to,
final String sid, final String localIP, final int port) { final String sid, final String localIP, final int port) {
@ -500,11 +505,11 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
* Returns the packet to send notification to the stream host to activate * Returns the packet to send notification to the stream host to activate
* the stream. * the stream.
* *
* @param sessionID The session ID of the file transfer to activate. * @param sessionID the session ID of the file transfer to activate.
* @param from * @param from
* @param to The JID of the stream host * @param to the JID of the stream host
* @param target The JID of the file transfer target. * @param target the JID of the file transfer target.
* @return Returns the packet to send notification to the stream host to * @return the packet to send notification to the stream host to
* activate the stream. * activate the stream.
*/ */
private static Bytestream createByteStreamActivate(final String sessionID, private static Bytestream createByteStreamActivate(final String sessionID,
@ -522,8 +527,8 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
* Negotiates the Socks 5 bytestream when the local computer is acting as * Negotiates the Socks 5 bytestream when the local computer is acting as
* the proxy. * the proxy.
* *
* @param connection The socket connection with the peer. * @param connection the socket connection with the peer.
* @return The SHA-1 digest that is used to uniquely identify the file * @return the SHA-1 digest that is used to uniquely identify the file
* transfer. * transfer.
* @throws XMPPException * @throws XMPPException
* @throws IOException * @throws IOException
@ -631,6 +636,14 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
} }
public void cleanup() { public void cleanup() {
synchronized (processLock) {
if (proxyProcess != null) {
proxyProcess.stop();
}
}
}
public void cancel() {
} }
private static class SelectedHostInfo { private static class SelectedHostInfo {
@ -652,9 +665,9 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
private class ProxyProcess implements Runnable { private class ProxyProcess implements Runnable {
private ServerSocket listeningSocket; private final ServerSocket listeningSocket;
private Map connectionMap = new HashMap(); private final Map connectionMap = new HashMap();
private boolean done = false; private boolean done = false;
@ -663,46 +676,67 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
public void run() { public void run() {
try { try {
listeningSocket.setSoTimeout(10000); try {
} listeningSocket.setSoTimeout(10000);
catch (SocketException e) { }
e.printStackTrace(); catch (SocketException e) {
} // There was a TCP error, lets print the stack trace
while (!done) { e.printStackTrace();
Socket conn = null; return;
synchronized (ProxyProcess.this) { }
while (transfers <= 0) { while (!done) {
transfers = -1; Socket conn = null;
try { synchronized (ProxyProcess.this) {
ProxyProcess.this.wait(); while (transfers <= 0 && !done) {
transfers = -1;
try {
ProxyProcess.this.wait();
}
catch (InterruptedException e) {
/* Do nothing */
}
} }
catch (InterruptedException e) { }
if(done) {
break;
}
try {
synchronized (listeningSocket) {
conn = listeningSocket.accept();
}
if (conn == null) {
continue;
}
String digest = establishSocks5UploadConnection(conn);
synchronized (connectionMap) {
connectionMap.put(digest, conn);
}
}
catch (SocketTimeoutException e) {
/* Do Nothing */
}
catch (IOException e) {
/* Do Nothing */
}
catch (XMPPException e) {
e.printStackTrace();
if (conn != null) {
try {
conn.close();
}
catch (IOException e1) {
/* Do Nothing */
}
} }
} }
} }
}
finally {
try { try {
synchronized (listeningSocket) { listeningSocket.close();
conn = listeningSocket.accept();
}
if (conn == null) {
continue;
}
String digest = establishSocks5UploadConnection(conn);
synchronized (connectionMap) {
connectionMap.put(digest, conn);
}
} }
catch (IOException e) { catch (IOException e) {
} /* Do Nothing */
catch (XMPPException e) {
e.printStackTrace();
if (conn != null) {
try {
conn.close();
}
catch (IOException e1) {
}
}
} }
} }
} }
@ -717,6 +751,9 @@ public class Socks5TransferNegotiator extends StreamNegotiator {
synchronized (this) { synchronized (this) {
this.notify(); this.notify();
} }
synchronized (listeningSocket) {
listeningSocket.notify();
}
} }
public int getPort() { public int getPort() {