Changeset 461

Show
Ignore:
Timestamp:
07/21/07 09:37:11 (1 year ago)
Author:
blackhedd
Message:

refactored this class into an interface

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • version_0/java/src/com/rubyeventmachine/EventableChannel.java

    r450 r461  
    1 /** 
    2  *  
    3  */ 
    41package com.rubyeventmachine; 
    52 
    6 /** 
    7  * @author francis 
    8  * 
    9  */ 
     3import java.nio.ByteBuffer; 
    104 
    11 import java.nio.channels.*; 
    12 import java.nio.*; 
    13 import java.util.*; 
    14 import java.io.*; 
    15 import javax.net.ssl.*; 
    16 import javax.net.ssl.SSLEngineResult.*; 
    17  
    18 import java.security.*; 
    19  
    20 public class EventableChannel { 
     5public interface EventableChannel { 
    216         
    22         // TODO, must refactor this to permit channels that aren't sockets. 
    23         SocketChannel myChannel; 
    24         String myBinding; 
    25         Selector mySelector; 
    26         LinkedList<ByteBuffer> OutboundQ; 
    27         boolean bCloseScheduled; 
     7        public void scheduleOutboundData (ByteBuffer bb); 
    288         
    29         SSLEngine sslEngine
     9        public void scheduleOutboundDatagram (ByteBuffer bb, String recipAddress, int recipPort)
    3010         
     11        public void scheduleClose (boolean afterWriting); 
    3112         
    32         SSLContext sslContext; 
    33  
    34  
    35         public EventableChannel (SocketChannel sc, String binding, Selector sel) throws ClosedChannelException { 
    36                 myChannel = sc; 
    37                 myBinding = binding; 
    38                 mySelector = sel; 
    39                 bCloseScheduled = false; 
    40                 OutboundQ = new LinkedList<ByteBuffer>(); 
    41                  
    42                 sc.register(mySelector, SelectionKey.OP_READ, this); 
    43         } 
     13        public void startTls(); 
    4414         
    45         public String getBinding() { 
    46                 return myBinding; 
    47         } 
    48         public void scheduleOutboundData (ByteBuffer bb) throws ClosedChannelException, SSLException { 
    49                 if ((!bCloseScheduled) && (bb.remaining() > 0)) { 
    50                         if (sslEngine != null) { 
    51                                 ByteBuffer b = ByteBuffer.allocate(32*1024); // TODO, preallocate this buffer. 
    52                                 sslEngine.wrap(bb, b); 
    53                                 b.flip(); 
    54                                 OutboundQ.addLast(b); 
    55                         } 
    56                         else { 
    57                                 OutboundQ.addLast(bb); 
    58                         } 
    59                         myChannel.register(mySelector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, this); 
    60                 } 
    61         } 
     15        public String getBinding(); 
     16         
     17        public void readInboundData (ByteBuffer dst); 
    6218         
    6319        /** 
    64          * Called by the reactor when we have selected writable. 
    65          * Return false to indicate an error that should cause the connection to close. 
    66          * We can get here with an empty outbound buffer if bCloseScheduled is true. 
    67          * @return 
     20         * This is called by the reactor after it finishes running. 
     21         * The idea is to free network resources. 
    6822         */ 
    69         public boolean writeOutboundData() throws ClosedChannelException { 
    70                 while (!OutboundQ.isEmpty()) { 
    71                         ByteBuffer b = OutboundQ.getFirst(); 
    72                         try { 
    73                                 myChannel.write(b); 
    74                         } 
    75                         catch (IOException e) { 
    76                                 return false; 
    77                         } 
    78                         if (b.remaining() == 0) 
    79                                 OutboundQ.removeFirst(); 
    80                         else 
    81                                 break; 
    82                 } 
    83  
    84                 if (OutboundQ.isEmpty()) 
    85                         myChannel.register(mySelector, SelectionKey.OP_READ, this); 
    86  
    87                 // ALWAYS drain the outbound queue before triggering a connection close. 
    88                 // If anyone wants to close immediately, they're responsible for clearing 
    89                 // the outbound queue. 
    90                 return (bCloseScheduled && OutboundQ.isEmpty()) ? false : true; 
    91         } 
     23        public void close(); 
    9224         
    93         public void setConnectPending() throws ClosedChannelException { 
    94                 myChannel.register(mySelector, SelectionKey.OP_CONNECT, this); 
    95         } 
    96          
    97         /** 
    98          * Called by the reactor when we have selected connectable. 
    99          * Return false to indicate an error that should cause the connection to close. 
    100          * @throws ClosedChannelException 
    101          */ 
    102         public boolean finishConnecting() throws ClosedChannelException { 
    103                 try { 
    104                         myChannel.finishConnect(); 
    105                 } 
    106                 catch (IOException e) { 
    107                         return false; 
    108                 } 
    109                 myChannel.register(mySelector, SelectionKey.OP_READ, this); 
    110                 return true; 
    111         } 
    112          
    113         public void scheduleClose (boolean afterWriting) throws ClosedChannelException { 
    114                 if (!afterWriting) 
    115                         OutboundQ.clear(); 
    116                 myChannel.register(mySelector, SelectionKey.OP_READ|SelectionKey.OP_WRITE, this); 
    117                 bCloseScheduled = true; 
    118         } 
    119         public void startTls() throws NoSuchAlgorithmException, KeyManagementException { 
    120                 if (sslEngine == null) { 
    121                         sslContext = SSLContext.getInstance("TLS"); 
    122                         sslContext.init(null, null, null); // TODO, fill in the parameters. 
    123                         sslEngine = sslContext.createSSLEngine(); // TODO, should use the parameterized version, to get Kerb stuff and session re-use. 
    124                         sslEngine.setUseClientMode(false); 
    125                 } 
    126                 System.out.println ("Starting TLS"); 
    127         } 
    128          
    129         public ByteBuffer dispatchInboundData (ByteBuffer bb) throws SSLException { 
    130                 if (sslEngine != null) { 
    131                         if (true) throw new RuntimeException ("TLS currently unimplemented"); 
    132                         System.setProperty("javax.net.debug", "all"); 
    133                         ByteBuffer w = ByteBuffer.allocate(32*1024); // TODO, WRONG, preallocate this buffer. 
    134                         SSLEngineResult res = sslEngine.unwrap(bb, w); 
    135                         if (res.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { 
    136                                 Runnable r; 
    137                                 while ((r = sslEngine.getDelegatedTask()) != null) { 
    138                                         r.run(); 
    139                                 } 
    140                         } 
    141                         System.out.println (bb); 
    142                         w.flip(); 
    143                         return w; 
    144                 } 
    145                 else 
    146                         return bb; 
    147         } 
     25        public boolean writeOutboundData(); 
    14826}