Skip to content

Commit aa46b73

Browse files
committed
fixed more ssl bugs
1 parent 5c6b8bb commit aa46b73

2 files changed

Lines changed: 88 additions & 57 deletions

File tree

‎src/org/java_websocket/SSLSocketChannel2.java‎

Lines changed: 85 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -13,73 +13,85 @@
1313
import java.nio.channels.SelectableChannel;
1414
import java.nio.channels.SelectionKey;
1515
import java.nio.channels.SocketChannel;
16+
import java.util.ArrayList;
17+
import java.util.Iterator;
18+
import java.util.List;
1619
import java.util.concurrent.ExecutorService;
20+
import java.util.concurrent.Future;
1721

1822
import javax.net.ssl.SSLEngine;
1923
import javax.net.ssl.SSLEngineResult;
2024
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
25+
import javax.net.ssl.SSLEngineResult.Status;
2126
import javax.net.ssl.SSLException;
2227
import javax.net.ssl.SSLSession;
2328

2429
/**
2530
* Implements the relevant portions of the SocketChannel interface with the SSLEngine wrapper.
2631
*/
2732
public class SSLSocketChannel2 implements ByteChannel, WrappedByteChannel {
28-
private static ByteBuffer emptybuffer = ByteBuffer.allocate( 0 );
33+
protected static ByteBuffer emptybuffer = ByteBuffer.allocate( 0 );
2934

30-
private ExecutorService exec;
35+
protected ExecutorService exec;
36+
37+
protected List<Future<?>> tasks;
3138

3239
/** raw payload incomming */
33-
private ByteBuffer inData;
40+
protected ByteBuffer inData;
3441
/** encrypted data outgoing */
35-
private ByteBuffer outCrypt;
42+
protected ByteBuffer outCrypt;
3643
/** encrypted data incoming */
37-
private ByteBuffer inCrypt;
44+
protected ByteBuffer inCrypt;
3845

39-
private SocketChannel sc;
40-
private SelectionKey key;
46+
protected SocketChannel sc;
47+
protected SelectionKey key;
4148

42-
private SSLEngineResult res;
43-
private SSLEngine sslEngine;
49+
protected SSLEngineResult res;
50+
protected SSLEngine sslEngine;
4451

4552
public SSLSocketChannel2( SelectionKey key , SSLEngine sslEngine , ExecutorService exec ) throws IOException {
4653
this.sc = (SocketChannel) key.channel();
4754
this.key = key;
4855
this.sslEngine = sslEngine;
4956
this.exec = exec;
5057

58+
tasks = new ArrayList<Future<?>>( 3 );
59+
5160
this.key.interestOps( key.interestOps() | SelectionKey.OP_WRITE );
5261

5362
sslEngine.setEnableSessionCreation( true );
5463
SSLSession session = sslEngine.getSession();
5564
createBuffers( session );
5665

57-
// there is not yet any user data
58-
inData.flip();
59-
inCrypt.flip();
60-
outCrypt.flip();
61-
62-
sc.write( wrap( emptybuffer ) );
63-
66+
sc.write( wrap( emptybuffer ) );// initializes res
6467
processHandshake();
6568
}
6669

67-
private boolean processHandshake() throws IOException {
70+
private void processHandshake() throws IOException {
71+
if( !tasks.isEmpty() ) {
72+
Iterator<Future<?>> it = tasks.iterator();
73+
while ( it.hasNext() ) {
74+
Future<?> f = it.next();
75+
if( f.isDone() ) {
76+
it.remove();
77+
} else {
78+
return;
79+
}
80+
}
81+
}
82+
6883
if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
6984
inCrypt.compact();
7085
sc.read( inCrypt );
7186
inCrypt.flip();
87+
inData.compact();
7288
unwrap();
73-
if( res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED ) {
74-
sc.write( wrap( emptybuffer ) );
75-
}
76-
} else if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) {
89+
}
90+
consumeDelegatedTasks();
91+
if( tasks.isEmpty() || res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) {
7792
sc.write( wrap( emptybuffer ) );
78-
} else {
79-
assert ( false );
8093
}
8194

82-
return false;
8395
}
8496

8597
private synchronized ByteBuffer wrap( ByteBuffer b ) throws SSLException {
@@ -90,59 +102,59 @@ private synchronized ByteBuffer wrap( ByteBuffer b ) throws SSLException {
90102
}
91103

92104
private synchronized ByteBuffer unwrap() throws SSLException {
93-
inData.compact();
94-
while ( inCrypt.hasRemaining() ) {
105+
int rem;
106+
do{
107+
rem = inData.remaining();
95108
res = sslEngine.unwrap( inCrypt, inData );
96-
if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK ) {
97-
Runnable task;
98-
while ( ( task = sslEngine.getDelegatedTask() ) != null ) {
99-
task.run();
100-
}
101-
} else if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED ) {
102-
break;
103-
} else if( res.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW ) {
104-
break;
105-
} else if( res.getStatus() == SSLEngineResult.Status.BUFFER_OVERFLOW ) {
106-
throw new RuntimeException( "destenation buffer to small" );
107-
}
108-
}
109+
} while ( rem != inData.remaining() );
110+
109111
inData.flip();
110112
return inData;
111113
}
112114

115+
protected void consumeDelegatedTasks() {
116+
Runnable task;
117+
while ( ( task = sslEngine.getDelegatedTask() ) != null ) {
118+
tasks.add( exec.submit( task ) );
119+
// task.run();
120+
}
121+
}
122+
113123
protected void createBuffers( SSLSession session ) {
114124
int appBufferMax = session.getApplicationBufferSize();
115125
int netBufferMax = session.getPacketBufferSize();
116126

117127
inData = ByteBuffer.allocate( appBufferMax );
118128
outCrypt = ByteBuffer.allocate( netBufferMax );
119129
inCrypt = ByteBuffer.allocate( netBufferMax );
130+
inData.flip();
131+
inCrypt.flip();
132+
outCrypt.flip();
120133
}
121134

122135
public int write( ByteBuffer src ) throws IOException {
123136
if( !isHandShakeComplete() ) {
124137
processHandshake();
125138
return 0;
126-
} else {
127-
return sc.write( wrap( src ) );
128139
}
140+
int num = sc.write( wrap( src ) );
141+
return num;
142+
129143
}
130144

131145
public int read( ByteBuffer dst ) throws IOException {
132146
if( !isHandShakeComplete() ) {
133147
processHandshake();
134148
return 0;
135149
}
136-
int amount = 0, limit;
137-
// test if there was a buffer overflow in dst
138-
if( inData.hasRemaining() ) {
139-
return transfereTo( inData, dst );
140-
}
141-
// test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
142-
if( inCrypt.hasRemaining() ) {
143-
unwrap();
144-
amount += transfereTo( inData, dst );
145-
}
150+
151+
int purged = readRemaining( dst );
152+
if( purged != 0 )
153+
return purged;
154+
155+
assert ( inData.position() == 0 );
156+
inData.clear();
157+
146158
if( !inCrypt.hasRemaining() )
147159
inCrypt.clear();
148160
else
@@ -153,11 +165,28 @@ public int read( ByteBuffer dst ) throws IOException {
153165
}
154166
inCrypt.flip();
155167
unwrap();
156-
amount += transfereTo( inData, dst );
157-
return amount;
168+
return transfereTo( inData, dst );
158169

159170
}
160171

172+
private int readRemaining( ByteBuffer dst ) throws SSLException {
173+
assert ( dst.hasRemaining() );
174+
175+
if( inData.hasRemaining() ) {
176+
return transfereTo( inData, dst );
177+
}
178+
assert ( !inData.hasRemaining() );
179+
inData.clear();
180+
// test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
181+
if( inCrypt.hasRemaining() ) {
182+
unwrap();
183+
int amount = transfereTo( inData, dst );
184+
if( amount > 0 )
185+
return amount;
186+
}
187+
return 0;
188+
}
189+
161190
public boolean isConnected() {
162191
return sc.isConnected();
163192
}
@@ -211,12 +240,12 @@ public void writeMore() throws IOException {
211240

212241
@Override
213242
public boolean isNeedRead() {
214-
return inData.hasRemaining();
243+
return inData.hasRemaining() || ( inCrypt.hasRemaining() && res.getStatus() != Status.BUFFER_UNDERFLOW );
215244
}
216245

217246
@Override
218-
public int readMore( ByteBuffer dst ) {
219-
return transfereTo( inData, dst );
247+
public int readMore( ByteBuffer dst ) throws SSLException {
248+
return readRemaining( dst );
220249
}
221250

222251
private int transfereTo( ByteBuffer from, ByteBuffer to ) {

‎src/org/java_websocket/WrappedByteChannel.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
import java.nio.ByteBuffer;
55
import java.nio.channels.ByteChannel;
66

7+
import javax.net.ssl.SSLException;
8+
79
public interface WrappedByteChannel extends ByteChannel {
810
public boolean isNeedWrite();
911
public void writeMore() throws IOException;
1012

1113
public boolean isNeedRead();
12-
public int readMore( ByteBuffer dst );
14+
public int readMore( ByteBuffer dst ) throws SSLException;
1315
}

0 commit comments

Comments
 (0)