Openfire 3.5.1 compression bug fix

When xep 0138 is used, a.k.a., cli/srv compression, the server periodically drops connections. Various folks have mentioned related problems in the support lists. logs/warn.log suggests an ArrayIndexOutOfBoundsException with mina.

org.apache.mina.filter.codec.ProtocolDecoderException: java.lang.ArrayIndexOutOfBoundsException (Hexdump: empty)

at org.apache.mina.filter.codec.ProtocolCodecFilter.messageReceived(ProtocolCodecF ilter.java:165)

at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:299)

at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilt erChain.java:53)

at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceive d(AbstractIoFilterChain.java:648)

at org.apache.mina.filter.CompressionFilter.messageReceived(CompressionFilter.java :161)

at org.apache.mina.common.support.AbstractIoFilterChain.callNextMessageReceived(Ab stractIoFilterChain.java:299)

at org.apache.mina.common.support.AbstractIoFilterChain.access$1100(AbstractIoFilt erChain.java:53)

at org.apache.mina.common.support.AbstractIoFilterChain$EntryImpl$1.messageReceive d(AbstractIoFilterChain.java:648)

at org.apache.mina.filter.executor.ExecutorFilter.processEvent(ExecutorFilter.java :239)

at org.apache.mina.filter.executor.ExecutorFilter$ProcessEventsRunnable.run(Execut orFilter.java:283)

at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java: 650)

at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:675)

at org.apache.mina.util.NamePreservingRunnable.run(NamePreservingRunnable.java:51)

at java.lang.Thread.run(Thread.java:613)

Caused by: java.lang.ArrayIndexOutOfBoundsException

It turns out that the problem has two pieces, one related to mina, and the other to openfire.

In org/jivesoftware/openfire/nio/XMLLightweightParser.java:read, readByte can be 0. In this case, readByte-1 is -1, which leads to an exception.

The mina code in org/apache/mina/filter/codec/CumulativeProtocolDecoder.java:decode leads to this problem. It’s possible that an attempt is made to decode a zero-byte buffer. A conditional check fixes the problem.

Here are the fixes for openfire 3.5.1 and mina 1.1.7. I hope they can be incorporated as soon as possible.

Regards,

Joe

svn:mime-type = application/octet-stream
Index: openfire_src/src/java/org/apache/mina/management/MINAStatCollector.java
===================================================================
--- openfire_src/src/java/org/apache/mina/management/MINAStatCollector.java     (revision 1408)
+++ openfire_src/src/java/org/apache/mina/management/MINAStatCollector.java     (revision 1412)
@@ -8,6 +8,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.ThreadPoolExecutor; /**
  * Collects statistics of an {@link org.apache.mina.common.IoService}. It's polling all the sessions of a given
@@ -306,7 +307,7 @@
                     ExecutorFilter executorFilter =
                             (ExecutorFilter) session.getFilterChain().get(ExecutorThreadModel.class.getName());
                     if (executorFilter != null) {
-                        tmpQueuevedEvents += executorFilter.getEventQueueSize(session);
+                        tmpQueuevedEvents += ((ThreadPoolExecutor) executorFilter.getExecutor()).getQueue().size();
                     }                      sessStat.lastByteRead = readBytes; Index: openfire_src/src/java/org/jivesoftware/openfire/nio/XMLLightweightParser.java
===================================================================
--- openfire_src/src/java/org/jivesoftware/openfire/nio/XMLLightweightParser.java     (revision 1408)
+++ openfire_src/src/java/org/jivesoftware/openfire/nio/XMLLightweightParser.java     (revision 1412)
@@ -154,6 +154,9 @@
         CharBuffer charBuffer = encoder.decode(byteBuffer.buf());
         char[] buf = charBuffer.array();
         int readByte = charBuffer.remaining();
+        if (readByte == 0) {
+             return;
+        }          // Verify if the last received byte is an incomplete double byte character
         char lastChar = buf[readByte-1]; Index: mina-1.1.7/core/src/main/java/org/apache/mina/filter/codec/CumulativeProtocolDecoder.java
===================================================================
--- mina-1.1.7/core/src/main/java/org/apache/mina/filter/codec/CumulativeProtocolDecoder.java     (revision 1407)
+++ mina-1.1.7/core/src/main/java/org/apache/mina/filter/codec/CumulativeProtocolDecoder.java     (revision 1412)
@@ -128,20 +128,12 @@
             usingSessionBuffer = false;
         } -        for (;;) {
+        boolean decoded = true;
+        for (;buf.hasRemaining() && decoded;) {
             int oldPos = buf.position();
-            boolean decoded = doDecode(session, buf, out);
-            if (decoded) {
-                if (buf.position() == oldPos) {
-                    throw new IllegalStateException(
-                            "doDecode() can't return true when buffer is not consumed.");
-                }
-
-                if (!buf.hasRemaining()) {
-                    break;
-                }
-            } else {
-                break;
+            decoded = doDecode(session, buf, out);
+            if (decoded && buf.position() == oldPos) {
+                 throw new IllegalStateException("doDecode() can't return true when buffer is not consumed.");
             }
         }

Wow!

It sounds very very good

Hey Joe,

Impressive!!! I will check now your bug fix and check it in if it looks good.

Thanks a lot for catching this one.

– Gato

Quick question…if things look ok, will you push the mina fix back to the mina team?

Joe

Hey Joe,

In fact I forwarded your fix to the MINA devs and I’m waiting for their feedback. Unfortunately, I suspect that you are fixing another issue and not the old compression problem that we noticed a few times. Anyway, this seems to be a good fix.

Thanks,

– Gato

Hopefully one can fix then JM-1115.