1313import java .nio .channels .SelectableChannel ;
1414import java .nio .channels .SelectionKey ;
1515import java .nio .channels .SocketChannel ;
16+ import java .util .concurrent .ExecutorService ;
1617
1718import javax .net .ssl .SSLEngine ;
1819import javax .net .ssl .SSLEngineResult ;
2627public class SSLSocketChannel2 implements ByteChannel , WrappedByteChannel {
2728 private static ByteBuffer emptybuffer = ByteBuffer .allocate ( 0 );
2829
30+ private ExecutorService exec ;
31+
2932 /** raw payload incomming */
3033 private ByteBuffer inData ;
3134 /** encrypted data outgoing */
@@ -39,12 +42,13 @@ public class SSLSocketChannel2 implements ByteChannel, WrappedByteChannel {
3942 private SSLEngineResult res ;
4043 private SSLEngine sslEngine ;
4144
42- public SSLSocketChannel2 ( SelectionKey key , SSLEngine sslEngine ) throws IOException {
45+ public SSLSocketChannel2 ( SelectionKey key , SSLEngine sslEngine , ExecutorService exec ) throws IOException {
4346 this .sc = (SocketChannel ) key .channel ();
4447 this .key = key ;
4548 this .sslEngine = sslEngine ;
49+ this .exec = exec ;
4650
47- key .interestOps ( key .interestOps () | SelectionKey .OP_WRITE );
51+ this . key .interestOps ( key .interestOps () | SelectionKey .OP_WRITE );
4852
4953 sslEngine .setEnableSessionCreation ( true );
5054 SSLSession session = sslEngine .getSession ();
@@ -55,21 +59,18 @@ public SSLSocketChannel2( SelectionKey key , SSLEngine sslEngine ) throws IOExce
5559 inCrypt .flip ();
5660 outCrypt .flip ();
5761
58- wrap ( emptybuffer );
62+ sc . write ( wrap ( emptybuffer ) );
5963
6064 processHandshake ();
6165 }
6266
6367 private boolean processHandshake () throws IOException {
6468 if ( res .getHandshakeStatus () == SSLEngineResult .HandshakeStatus .NEED_UNWRAP ) {
65- if ( !inCrypt .hasRemaining () )
66- inCrypt .clear ();
69+ inCrypt .compact ();
6770 sc .read ( inCrypt );
6871 inCrypt .flip ();
6972 unwrap ();
7073 if ( res .getHandshakeStatus () != SSLEngineResult .HandshakeStatus .FINISHED ) {
71- // if( !outData.hasRemaining() )
72- // outData.clear();
7374 sc .write ( wrap ( emptybuffer ) );
7475 }
7576 } else if ( res .getHandshakeStatus () == SSLEngineResult .HandshakeStatus .NEED_WRAP ) {
@@ -82,8 +83,7 @@ private boolean processHandshake() throws IOException {
8283 }
8384
8485 private synchronized ByteBuffer wrap ( ByteBuffer b ) throws SSLException {
85- if ( !outCrypt .hasRemaining () )
86- outCrypt .clear ();
86+ outCrypt .compact ();
8787 res = sslEngine .wrap ( b , outCrypt );
8888 outCrypt .flip ();
8989 return outCrypt ;
@@ -94,7 +94,6 @@ private synchronized ByteBuffer unwrap() throws SSLException {
9494 while ( inCrypt .hasRemaining () ) {
9595 res = sslEngine .unwrap ( inCrypt , inData );
9696 if ( res .getHandshakeStatus () == SSLEngineResult .HandshakeStatus .NEED_TASK ) {
97- // Task
9897 Runnable task ;
9998 while ( ( task = sslEngine .getDelegatedTask () ) != null ) {
10099 task .run ();
@@ -104,19 +103,18 @@ private synchronized ByteBuffer unwrap() throws SSLException {
104103 } else if ( res .getStatus () == SSLEngineResult .Status .BUFFER_UNDERFLOW ) {
105104 break ;
106105 } else if ( res .getStatus () == SSLEngineResult .Status .BUFFER_OVERFLOW ) {
107- assert ( false );
106+ throw new RuntimeException ( "destenation buffer to small" );
108107 }
109108 }
110109 inData .flip ();
111110 return inData ;
112111 }
113112
114- private void createBuffers ( SSLSession session ) {
113+ protected void createBuffers ( SSLSession session ) {
115114 int appBufferMax = session .getApplicationBufferSize ();
116115 int netBufferMax = session .getPacketBufferSize ();
117116
118- inData = ByteBuffer .allocate ( 65536 );
119-
117+ inData = ByteBuffer .allocate ( appBufferMax );
120118 outCrypt = ByteBuffer .allocate ( netBufferMax );
121119 inCrypt = ByteBuffer .allocate ( netBufferMax );
122120 }
@@ -138,47 +136,24 @@ public int read( ByteBuffer dst ) throws IOException {
138136 int amount = 0 , limit ;
139137 // test if there was a buffer overflow in dst
140138 if ( inData .hasRemaining () ) {
141- limit = Math .min ( inData .remaining (), dst .remaining () );
142- for ( int i = 0 ; i < limit ; i ++ ) {
143- dst .put ( inData .get () );
144- amount ++;
145- }
146- return amount ;
139+ return transfereTo ( inData , dst );
147140 }
148141 // test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
149142 if ( inCrypt .hasRemaining () ) {
150143 unwrap ();
151- inData .flip ();
152- limit = Math .min ( inData .limit (), dst .remaining () );
153- for ( int i = 0 ; i < limit ; i ++ ) {
154- dst .put ( inData .get () );
155- amount ++;
156- }
157- if ( res .getStatus () != SSLEngineResult .Status .BUFFER_UNDERFLOW ) {
158- inCrypt .clear ();
159- inCrypt .flip ();
160- return amount ;
161- }
144+ amount += transfereTo ( inData , dst );
162145 }
163146 if ( !inCrypt .hasRemaining () )
164147 inCrypt .clear ();
165148 else
166149 inCrypt .compact ();
167150
168151 if ( sc .read ( inCrypt ) == -1 ) {
169- inCrypt .clear ();
170- inCrypt .flip ();
171152 return -1 ;
172153 }
173154 inCrypt .flip ();
174155 unwrap ();
175- // write in dst
176- // inData.flip();
177- limit = Math .min ( inData .limit (), dst .remaining () );
178- for ( int i = 0 ; i < limit ; i ++ ) {
179- dst .put ( inData .get () );
180- amount ++;
181- }
156+ amount += transfereTo ( inData , dst );
182157 return amount ;
183158
184159 }
@@ -190,12 +165,11 @@ public boolean isConnected() {
190165 public void close () throws IOException {
191166 sslEngine .closeOutbound ();
192167 sslEngine .getSession ().invalidate ();
193- outCrypt .compact ();
194168 int wr = sc .write ( wrap ( emptybuffer ) );
195169 sc .close ();
196170 }
197171
198- private boolean isHandShakeComplete (){
172+ private boolean isHandShakeComplete () {
199173 HandshakeStatus status = res .getHandshakeStatus ();
200174 return status == SSLEngineResult .HandshakeStatus .FINISHED || status == SSLEngineResult .HandshakeStatus .NOT_HANDSHAKING ;
201175 }
@@ -231,7 +205,35 @@ public boolean isNeedWrite() {
231205 }
232206
233207 @ Override
234- public void write () throws IOException {
208+ public void writeMore () throws IOException {
235209 write ( emptybuffer );
236210 }
211+
212+ @ Override
213+ public boolean isNeedRead () {
214+ return inData .hasRemaining ();
215+ }
216+
217+ @ Override
218+ public int readMore ( ByteBuffer dst ) {
219+ return transfereTo ( inData , dst );
220+ }
221+
222+ private int transfereTo ( ByteBuffer from , ByteBuffer to ) {
223+ int fremain = from .remaining ();
224+ int toremain = to .remaining ();
225+ if ( fremain > toremain ) {
226+ // FIXME there should be a more efficient transfer method
227+ int limit = Math .min ( fremain , toremain );
228+ for ( int i = 0 ; i < limit ; i ++ ) {
229+ to .put ( from .get () );
230+ }
231+ return limit ;
232+ } else {
233+ to .put ( from );
234+ return fremain ;
235+ }
236+
237+ }
238+
237239}
0 commit comments