You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by er...@apache.org on 2013/01/20 17:01:57 UTC

svn commit: r1435870 - in /james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty: IMAPServer.java ImapRequestFrameDecoder.java SwitchableDelimiterBasedFrameDecoder.java

Author: eric
Date: Sun Jan 20 16:01:56 2013
New Revision: 1435870

URL: http://svn.apache.org/viewvc?rev=1435870&view=rev
Log:
Fix APPEND IMAP command can result in JAMES IMAP waiting indefinitely for data with a SwitchableDelimiterBasedFrameDecoder (JAMES-1436)

Added:
    james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java
Modified:
    james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
    james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java

Modified: james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java
URL: http://svn.apache.org/viewvc/james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java?rev=1435870&r1=1435869&r2=1435870&view=diff
==============================================================================
--- james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java (original)
+++ james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/IMAPServer.java Sun Jan 20 16:01:56 2013
@@ -40,7 +40,6 @@ import org.jboss.netty.channel.ChannelPi
 import org.jboss.netty.channel.ChannelPipelineFactory;
 import org.jboss.netty.channel.ChannelUpstreamHandler;
 import org.jboss.netty.channel.group.ChannelGroup;
-import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
 import org.jboss.netty.handler.codec.frame.Delimiters;
 import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
 import org.jboss.netty.handler.execution.ExecutionHandler;
@@ -70,12 +69,10 @@ public class IMAPServer extends Abstract
 
     private boolean plainAuthDisallowed;
     
-    
     private int timeout;
     
     private int literalSizeLimit;
 
-
     // Use a big default
     public final static int DEFAULT_MAX_LINE_LENGTH = 65536;
 
@@ -155,7 +152,8 @@ public class IMAPServer extends Abstract
 
                 // Add the text line decoder which limit the max line length,
                 // don't strip the delimiter and use CRLF as delimiter
-                pipeline.addLast(FRAMER, new DelimiterBasedFrameDecoder(maxLineLength, false, Delimiters.lineDelimiter()));
+                // Use a SwitchableDelimiterBasedFrameDecoder, see JAMES-1436
+                pipeline.addLast(FRAMER, new SwitchableDelimiterBasedFrameDecoder(maxLineLength, false, Delimiters.lineDelimiter()));
                
                 Encryption secure = getEncryption();
                 if (secure != null && !secure.isStartTLS()) {

Modified: james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java
URL: http://svn.apache.org/viewvc/james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java?rev=1435870&r1=1435869&r2=1435870&view=diff
==============================================================================
--- james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java (original)
+++ james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java Sun Jan 20 16:01:56 2013
@@ -39,6 +39,7 @@ import org.jboss.netty.channel.Channel;
 import org.jboss.netty.channel.ChannelFutureListener;
 import org.jboss.netty.channel.ChannelHandler;
 import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.ChannelPipeline;
 import org.jboss.netty.channel.ChannelStateEvent;
 import org.jboss.netty.handler.codec.frame.FrameDecoder;
 
@@ -174,10 +175,15 @@ public class ImapRequestFrameDecoder ext
                     reader.consumeLine();
                 }
                 
-                ChannelHandler handler = (ChannelHandler) attachment.remove(FRAMER);
-                if (handler != null) {
-                    channel.getPipeline().addFirst(FRAMER, handler);
-                }
+                // Code portion commented further to JAMES-1436.
+                // TODO Remove if no negative feedback on JAMES-1436.
+//                ChannelHandler handler = (ChannelHandler) attachment.remove(FRAMER);
+//                if (handler != null) {
+//                    channel.getPipeline().addFirst(FRAMER, handler);
+//                }
+                
+                ((SwitchableDelimiterBasedFrameDecoder) channel.getPipeline().get(FRAMER)).enableFraming();
+                
                 attachment.clear();
                 return message;
             } catch (NettyImapRequestLineReader.NotEnoughDataException e) {
@@ -187,9 +193,17 @@ public class ImapRequestFrameDecoder ext
                 // store the needed data size for later usage
                 attachment.put(NEEDED_DATA, neededData);
                 
-
-                ChannelHandler handler = channel.getPipeline().remove(FRAMER);
-                attachment.put(FRAMER, handler);
+                final ChannelPipeline pipeline = channel.getPipeline();
+                final ChannelHandlerContext framerContext = pipeline.getContext(FRAMER);
+                
+                // Code portion commented further to JAMES-1436.
+                // TODO Remove if no negative feedback on JAMES-1436.
+//                ChannelHandler handler = channel.getPipeline().remove(FRAMER);
+//                attachment.put(FRAMER, handler);
+
+                // SwitchableDelimiterBasedFrameDecoder added further to JAMES-1436.
+                final SwitchableDelimiterBasedFrameDecoder framer = (SwitchableDelimiterBasedFrameDecoder) pipeline.get(FRAMER);
+                framer.disableFraming(framerContext);
                 
                 buffer.resetReaderIndex();
                 return null;

Added: james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java
URL: http://svn.apache.org/viewvc/james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java?rev=1435870&view=auto
==============================================================================
--- james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java (added)
+++ james/server/trunk/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/SwitchableDelimiterBasedFrameDecoder.java Sun Jan 20 16:01:56 2013
@@ -0,0 +1,64 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you 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.apache.james.imapserver.netty;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.jboss.netty.channel.ChannelHandlerContext;
+import org.jboss.netty.channel.Channels;
+import org.jboss.netty.channel.MessageEvent;
+import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
+
+public class SwitchableDelimiterBasedFrameDecoder extends DelimiterBasedFrameDecoder {
+
+	private volatile boolean framingEnabled = true;
+	private volatile ChannelBuffer cumulation;
+
+	public SwitchableDelimiterBasedFrameDecoder(final int maxFrameLength, final boolean stripDelimiter, final ChannelBuffer... delimiters) {
+		super(maxFrameLength, stripDelimiter, delimiters);
+	}
+
+	@Override
+	public synchronized void messageReceived(final ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
+		if(this.framingEnabled) {
+			super.messageReceived(ctx, e);
+		} else {
+			ctx.sendUpstream(e);
+		}
+	}
+
+	public synchronized void enableFraming() {
+		this.framingEnabled = true;
+
+	}
+
+	public synchronized void disableFraming(final ChannelHandlerContext ctx) {
+		this.framingEnabled = false;
+		if(this.cumulation != null && this.cumulation.readable()) {
+			final ChannelBuffer spareBytes = this.cumulation.readBytes(this.cumulation.readableBytes());
+			Channels.fireMessageReceived(ctx, spareBytes);
+		}
+	}
+
+	@Override
+	protected synchronized ChannelBuffer createCumulationDynamicBuffer(final ChannelHandlerContext ctx) {
+		this.cumulation = super.createCumulationDynamicBuffer(ctx);
+		return this.cumulation;
+	}
+}
\ No newline at end of file



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org