You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2008/08/30 06:33:15 UTC

svn commit: r690460 - in /tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net: SelectorCallback.java SelectorThread.java SelectorThreadNio.java

Author: costin
Date: Fri Aug 29 21:33:15 2008
New Revision: 690460

URL: http://svn.apache.org/viewvc?rev=690460&view=rev
Log:
Initial support for plugging in ssl


Modified:
    tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorCallback.java
    tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThread.java
    tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThreadNio.java

Modified: tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorCallback.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorCallback.java?rev=690460&r1=690459&r2=690460&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorCallback.java (original)
+++ tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorCallback.java Fri Aug 29 21:33:15 2008
@@ -31,12 +31,13 @@
  * seems cleaner and it's nice to be able to use APR more portably.
  * ( older version used long - but non-blocking connect needs a second param )
  */
-public class SelectorCallback {
+public class SelectorCallback implements SelectorThread.IOThreadRunnable,
+    SelectorThread.DataEvents {
   
   /** 
    * Called when the protocol is connected.
    */
-  public void connected(SelectorData selThread) 
+  public void connected(SelectorData sdata) 
           throws IOException {
   }
 
@@ -44,34 +45,34 @@
    * It is possible to write data. 
    * For both read and write - re-enable interest if you want more data. 
    */
-  public void dataWriteable(SelectorData selThread) throws IOException {
+  public void dataWriteable(SelectorData sdata) throws IOException {
   }
 
   /**
    * Data available for read.
    * For both read and write - re-enable interest if you want more data. 
    */
-  public void dataReceived(SelectorData selThread) throws IOException {
+  public void dataReceived(SelectorData sdata) throws IOException {
   }
   
   /** 
    * nextTimeEvent reached. 
    */
-  public void timeEvent(SelectorData selThread) {
+  public void timeEvent(SelectorData sdata) {
   }
 
   /**
  * @throws IOException  
    *  
    */
-  public void ioThreadRun(SelectorData selThread) throws IOException {
+  public void ioThreadRun(SelectorData sdata) throws IOException {
   }
 
   /** 
    * Close was detected, or an unhandled exception happened while processing
    * this callback.
    */
-  public void channelClosed(SelectorData selThread, Throwable ex) {
+  public void channelClosed(SelectorData sdata, Throwable ex) {
   }
   
   /**
@@ -83,7 +84,7 @@
    * TODO: is there any case where something else besides registering read
    * interest on the new connection is needed ? Maybe it could read some data ?
    */
-  public SelectorCallback connectionAccepted(SelectorData selThread, 
+  public SelectorCallback connectionAccepted(SelectorData sdata, 
                                              Channel sockC) {
     return null;
   }

Modified: tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThread.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThread.java?rev=690460&r1=690459&r2=690460&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThread.java (original)
+++ tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThread.java Fri Aug 29 21:33:15 2008
@@ -74,7 +74,11 @@
     int lastReadResult;
     int zeroReads = 0;
     int lastWriteResult;
+
+    public SelectorFilter ssl;
     
+    public int suspended = 0;
+
     public String toString() {
         StringBuffer sb = new StringBuffer();
         sb.append("SelData: ")
@@ -85,6 +89,47 @@
         return sb.toString();
     }
   }
+  
+  public static interface IOThreadRunnable {
+      public void ioThreadRun(SelectorData selThread) throws IOException;
+  }
+  
+  public static interface DataEvents {
+      /** 
+       * Called by selector thread when it can write data.
+       * SSL may consume sending data for negotiation.
+     * @throws IOException 
+       */
+      public void dataWriteable(SelectorData sdata) throws IOException;
+      
+      public void dataReceived(SelectorData sdata) throws IOException;
+  }
+
+  public static interface DataChannel {
+      public int writeNonBlocking(SelectorThread st, SelectorData sdata, 
+                                  ByteBuffer bb) throws IOException;
+      
+      public int readNonBlocking(SelectorThread st, SelectorData sdata, 
+                                 ByteBuffer bb) throws IOException;
+      
+  }
+  
+  /**
+   * Used for non-blocking SSL, gzip, etc
+   */
+  public static interface SelectorFilter extends DataEvents, DataChannel {
+  }
+  
+  public static interface SslSupport extends SelectorFilter {
+      
+      // For CONNECT, etc
+      public void startSSL();
+
+      // To force a new handshake
+      public void handshake();
+      
+      // TODO: get certs, etc
+  }
 
   // ----------- IO handling -----------
   protected long inactivityTimeout = 5000;
@@ -118,8 +163,8 @@
    * @param sc
    * @param nextTimer time to call the timeEvent() callback
    */
-  public void setTimerEventTime(SelectorData selectorData, long nextTimer) {
-      selectorData.nextTimeEvent = nextTimer;
+  public void setTimerEventTime(SelectorData sdata, long nextTimer) {
+      sdata.nextTimeEvent = nextTimer;
   }
   
   public int readNonBlocking(SelectorData sc, ByteBuffer bb) 
@@ -151,7 +196,10 @@
   { 
   }
 
-  public void ioThreadRun(SelectorData sdata) throws IOException {
+  public void runInSelectorThread(SelectorData sdata) throws IOException {
+  }
+
+  public void runInSelectorThread(Runnable cb) throws IOException {
   }
   
   /**
@@ -174,11 +222,11 @@
   public void readInterest(SelectorData sc, boolean readInterest) throws IOException {
   }
   
-  public int getPort(SelectorData sd, boolean remote) {
+  public int getPort(SelectorData sdata, boolean remote) {
       return 0;
   }
   
-  public InetAddress getAddress(SelectorData sd, boolean remote) {
+  public InetAddress getAddress(SelectorData sdata, boolean remote) {
       return null;
   }
 }
\ No newline at end of file

Modified: tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThreadNio.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThreadNio.java?rev=690460&r1=690459&r2=690460&view=diff
==============================================================================
--- tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThreadNio.java (original)
+++ tomcat/sandbox/tomcat-lite/coyote-extensions/org/apache/tomcat/util/net/SelectorThreadNio.java Fri Aug 29 21:33:15 2008
@@ -39,7 +39,9 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import org.apache.tomcat.util.modeler.Registry;
+import org.apache.tomcat.util.ObjectManager;
+import org.apache.tomcat.util.net.SelectorThread.IOThreadRunnable;
+import org.apache.tomcat.util.net.SelectorThread.SelectorData;
 
 /**
  * NIO implementation.
@@ -60,6 +62,8 @@
         new ArrayList<SelectorData>();
     ArrayList<SelectorData> runInterest = 
         new ArrayList<SelectorData>();
+    ArrayList<Runnable> runnableInterest = 
+        new ArrayList<Runnable>();
 
     AtomicInteger opened = new AtomicInteger();
     AtomicInteger closed = new AtomicInteger();
@@ -69,7 +73,7 @@
     // thread
     ArrayList<SelectorData> active = new ArrayList<SelectorData>();
 
-    boolean debug = false;
+    boolean debug = true;
     boolean running = true;
 
     long lastWakeup = System.currentTimeMillis(); // last time we woke
@@ -105,12 +109,8 @@
 
     public void setName(String n) {
         selectorThread.setName(n);
-        Registry registry = Registry.getRegistry(null, null);
-        try {
-            registry.registerComponent(this, ":name=" + n, "SelectorThread");
-        } catch (Exception e) {
-            e.printStackTrace();
-        }
+        ObjectManager.get().registerObject(this, "SelectorThread-" + n, 
+                "SelectorThread");
     }
 
     /**
@@ -213,8 +213,8 @@
                         //}
                         //checkChannelKey(cstate);
                         if (sdata.selKey != sk || sdata.channelData != sk.channel()) {
-                        sdata.selKey = sk;
-                        sdata.channelData = sk.channel();
+                            sdata.selKey = sk;
+                            sdata.channelData = sk.channel();
                         }
 
                         if (sk.isValid() && sk.isAcceptable()) {
@@ -264,7 +264,11 @@
                                             + sk.readyOps() + " " + cstate + 
                                             " " + sk);
                                 }
-                                cstate.dataWriteable(sdata);
+                                if(sdata.ssl != null) {
+                                    sdata.ssl.dataWriteable(sdata);
+                                } else {
+                                    cstate.dataWriteable(sdata);
+                                }
                                 
                                 if (sdata.lastWriteResult > 0 && 
                                         sdata.writeInterest) {
@@ -273,7 +277,7 @@
                                 }
                             }
 
-                            if (sk.isReadable()) {
+                            if (sk.isValid() && sk.isReadable()) {
                                 sdata.lastReadResult = 0;
                                 if (debug) {
                                     log.info("dataReceived " + selected 
@@ -282,12 +286,11 @@
                                             + sk.readyOps() + " " + cstate + 
                                             " " + sk);
                                 }
-                                cstate.dataReceived(sdata);
-//                                if (cstate.selectorData.lastReadResult > 0 && 
-//                                        cstate.selectorData.readInterest) {
-//                                    log.warning("SelectorThread: read interest" +
-//                                                " after incomplete read");
-//                                }
+                                if (sdata.ssl != null) {
+                                    sdata.ssl.dataReceived(sdata);
+                                } else {
+                                    cstate.dataReceived(sdata);
+                                }
                             }
                         } catch (Throwable t) {
                             t.printStackTrace();
@@ -449,12 +452,22 @@
     throws IOException {
         try {
             int off = bb.position();
-            int done = ((SocketChannel) selectorData.channelData).read(bb);
+
+            int done = 0;
+            
+            if (selectorData.ssl != null) {
+                done = selectorData.ssl.readNonBlocking(this, selectorData, bb);
+            } else {
+                done = ((SocketChannel) selectorData.channelData).read(bb);
+            }
+            
+            
             if (debug) {
                 log.info("-------------readNB rd=" + done + " bb.limit=" + 
                         bb.limit() + " pos=" + bb.position() + " " + selectorData.callback);
             }
             if (done > 0) {
+            
                 if (debug) {
                     String s = new String(bb.array(), off,
                             bb.position() - off);
@@ -495,6 +508,11 @@
     public int writeNonBlocking(SelectorData selectorData, ByteBuffer bb) 
             throws IOException {
         try {
+            if (selectorData.suspended != 0) {
+                // for example some SSL negotiation is going on
+                log.info("Suspended - no write possible");
+                return 0;
+            }
             if (debug) {
                 log.info("writeNB pos=" + bb.position() + " len=" + 
                         (bb.limit() - bb.position()) + " " + selectorData.callback);
@@ -504,7 +522,13 @@
                         bb.limit() - bb.position());
                 log.info("Data:\n" + s);
             }
-            int done = ((SocketChannel) selectorData.channelData).write(bb);
+
+            int done = 0;
+            if (selectorData.ssl != null) {
+                done = selectorData.ssl.writeNonBlocking(this, selectorData, bb);
+            } else {
+                done = ((SocketChannel) selectorData.channelData).write(bb);
+            }
             selectorData.lastWriteResult = done;
             return done;
         } catch(IOException ex) {
@@ -551,6 +575,8 @@
         selectorData.channelData = socketChannel;
         selectorData.channelData = socketChannel; // no key
         
+        // TODO: add SSL filter
+        
         socketChannel.connect(new InetSocketAddress(host,  port));
         opened.incrementAndGet();
         
@@ -618,6 +644,7 @@
         if( serverTimeout >= 0 ) {
             serverSocket.setSoTimeout( serverTimeout );
         }
+        
 
         ssc.configureBlocking(false);
 
@@ -625,7 +652,8 @@
         selectorData.channelData = ssc; // no key yet
         selectorData.callback = cstate; 
         // key will be set in pending
-        
+
+        // TODO: add SSL here
         
         synchronized (connectAcceptInterest) {
             connectAcceptInterest.add(selectorData);
@@ -633,7 +661,9 @@
         selector.wakeup();
     }
     
-    public void ioThreadRun(SelectorData sdata) throws IOException {
+
+    @Override
+    public void runInSelectorThread(SelectorData sdata) throws IOException {
         if (isSelectorThread()) {
             sdata.callback.ioThreadRun(sdata);
         } else {
@@ -643,6 +673,20 @@
             selector.wakeup();
         }
     }
+    
+    @Override
+    public void runInSelectorThread(Runnable cb) throws IOException {
+        if (isSelectorThread()) {
+            cb.run();
+        } else {
+            synchronized (runnableInterest) {
+                runnableInterest.add(cb);
+            }
+            selector.wakeup();
+        }
+        
+    }
+    
 
     /**
      * Example config: 
@@ -752,6 +796,8 @@
 
     @Override    
     public void writeInterest(SelectorData selectorData, boolean b) {
+        // TODO: suspended ? 
+
         SelectionKey sk = (SelectionKey) selectorData.selKey;
         if (!sk.isValid()) {
             return;
@@ -947,6 +993,23 @@
                 runInterest.clear();
             }
         }
+        if (runnableInterest.size() > 0) {
+            synchronized (runnableInterest) {
+                Iterator<Runnable> ci = runnableInterest.iterator();
+                while (ci.hasNext()) {
+                    Runnable cstate = ci.next();
+                    try {
+                        cstate.run();
+                    } catch (Throwable t) {
+                        t.printStackTrace();
+                    }
+                    if (debug) {
+                        log.info("Run in selthread: " + cstate);
+                    }
+                }
+                runnableInterest.clear();
+            }
+        }
         processPendingUpdateCallback();
     }
 
@@ -980,4 +1043,11 @@
             }
         }
     }
+
+    // SSL support - TODO: move to separate class, make it pluggable
+    // This uses plain java APIs
+    
+
+    
+    
 }
\ No newline at end of file



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