1
0
Fork 0
mirror of https://codeberg.org/Mercury-IM/Smack synced 2024-11-16 12:12:06 +01:00

Improve stream compression for TCP connections

Fix a race condition in useCompression where the compression request was
send outside the synchronized block, this could cause notify() to be
called without a previoius call to wait().

s/streamCompressionDenied/streamCompressionNegotiationDone/ and re-use
the method once the server ack'd stream compression.

Also don't call notifyConnectionError() when requestStreamCompression()
encounters an exception, instead throw the exception.
This commit is contained in:
Florian Schmaus 2014-04-27 11:39:38 +02:00
parent 9b235d0d8f
commit d17f64ed9a
2 changed files with 16 additions and 21 deletions

View file

@ -231,7 +231,7 @@ class PacketReader {
// Stream compression has been denied. This is a recoverable // Stream compression has been denied. This is a recoverable
// situation. It is still possible to authenticate and // situation. It is still possible to authenticate and
// use the connection but using an uncompressed connection // use the connection but using an uncompressed connection
connection.streamCompressionDenied(); connection.streamCompressionNegotiationDone();
} }
else { else {
// SASL authentication has failed. The server may close the connection // SASL authentication has failed. The server may close the connection

View file

@ -776,8 +776,9 @@ public class XMPPTCPConnection extends XMPPConnection {
* <p> * <p>
* *
* @return true if stream compression negotiation was successful. * @return true if stream compression negotiation was successful.
* @throws IOException if the compress stanza could not be send
*/ */
private boolean useCompression() { private boolean useCompression() throws IOException {
// If stream compression was offered by the server and we want to use // If stream compression was offered by the server and we want to use
// compression then send compression request to the server // compression then send compression request to the server
if (authenticated) { if (authenticated) {
@ -785,9 +786,9 @@ public class XMPPTCPConnection extends XMPPConnection {
} }
if ((compressionHandler = maybeGetCompressionHandler()) != null) { if ((compressionHandler = maybeGetCompressionHandler()) != null) {
requestStreamCompression(compressionHandler.getCompressionMethod());
// Wait until compression is being used or a timeout happened
synchronized (this) { synchronized (this) {
requestStreamCompression(compressionHandler.getCompressionMethod());
// Wait until compression is being used or a timeout happened
try { try {
wait(getPacketReplyTimeout()); wait(getPacketReplyTimeout());
} }
@ -804,24 +805,20 @@ public class XMPPTCPConnection extends XMPPConnection {
* Request the server that we want to start using stream compression. When using TLS * Request the server that we want to start using stream compression. When using TLS
* then negotiation of stream compression can only happen after TLS was negotiated. If TLS * then negotiation of stream compression can only happen after TLS was negotiated. If TLS
* compression is being used the stream compression should not be used. * compression is being used the stream compression should not be used.
* @throws IOException if the compress stanza could not be send
*/ */
private void requestStreamCompression(String method) { private void requestStreamCompression(String method) throws IOException {
try { writer.write("<compress xmlns='http://jabber.org/protocol/compress'>");
writer.write("<compress xmlns='http://jabber.org/protocol/compress'>"); writer.write("<method>" + method + "</method></compress>");
writer.write("<method>" + method + "</method></compress>"); writer.flush();
writer.flush();
}
catch (IOException e) {
notifyConnectionError(e);
}
} }
/** /**
* Start using stream compression since the server has acknowledged stream compression. * Start using stream compression since the server has acknowledged stream compression.
* *
* @throws Exception if there is an exception starting stream compression. * @throws IOException if there is an exception starting stream compression.
*/ */
void startStreamCompression() throws Exception { void startStreamCompression() throws IOException {
serverAckdCompression = true; serverAckdCompression = true;
// Initialize the reader and writer with the new secured version // Initialize the reader and writer with the new secured version
initReaderAndWriter(); initReaderAndWriter();
@ -831,16 +828,14 @@ public class XMPPTCPConnection extends XMPPConnection {
// Send a new opening stream to the server // Send a new opening stream to the server
packetWriter.openStream(); packetWriter.openStream();
// Notify that compression is being used // Notify that compression is being used
synchronized (this) { streamCompressionNegotiationDone();
this.notify();
}
} }
/** /**
* Notifies the XMPP connection that stream compression was denied so that * Notifies the XMPP connection that stream compression negotiation is done so that the
* the connection process can proceed. * connection process can proceed.
*/ */
synchronized void streamCompressionDenied() { synchronized void streamCompressionNegotiationDone() {
this.notify(); this.notify();
} }