Skip to content

Commit 0786b51

Browse files
committed
wss in progress commit
1 parent cd87e71 commit 0786b51

File tree

3 files changed

+234
-2
lines changed

3 files changed

+234
-2
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* Copyright (C) 2003 Alexander Kout
3+
* Originally from the jFxp project (http://jfxp.sourceforge.net/).
4+
* Copied with permission June 11, 2012 by Femi Omojola (fomojola@ideasynthesis.com).
5+
*/
6+
package org.java_websocket;
7+
8+
import java.io.IOException;
9+
import java.net.Socket;
10+
import java.net.SocketAddress;
11+
import java.nio.ByteBuffer;
12+
import java.nio.channels.ByteChannel;
13+
import java.nio.channels.SelectableChannel;
14+
import java.nio.channels.SelectionKey;
15+
import java.nio.channels.SocketChannel;
16+
17+
import javax.net.ssl.SSLEngine;
18+
import javax.net.ssl.SSLEngineResult;
19+
import javax.net.ssl.SSLException;
20+
import javax.net.ssl.SSLSession;
21+
22+
/**
23+
* Implements the relevant portions of the SocketChannel interface with the SSLEngine wrapper.
24+
*/
25+
public class SSLSocketChannel2 implements ByteChannel {
26+
/** raw payload incomming */
27+
private ByteBuffer clientIn;
28+
/** raw payload outgoing */
29+
private ByteBuffer clientOut;
30+
/** encrypted data outgoing */
31+
private ByteBuffer cTOs;
32+
/** encrypted data incoming */
33+
private ByteBuffer sTOc;
34+
35+
private SocketChannel sc;
36+
private SelectionKey key;
37+
38+
private SSLEngineResult res;
39+
private SSLEngine sslEngine;
40+
private int SSL;
41+
42+
public SSLSocketChannel2( SelectionKey key , SSLEngine sslEngine ) throws IOException {
43+
this.sc = (SocketChannel) key.channel();
44+
this.key = key;
45+
this.sslEngine = sslEngine;
46+
SSL = 1;
47+
try {
48+
sslEngine.setEnableSessionCreation( true );
49+
SSLSession session = sslEngine.getSession();
50+
createBuffers( session );
51+
// wrap
52+
clientOut.clear();
53+
sc.write( wrap( clientOut ) );
54+
assert ( !clientOut.hasRemaining() );
55+
while ( res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED ) {
56+
processHandshake();
57+
}
58+
clientIn.clear();
59+
clientIn.flip();
60+
SSL = 4;
61+
} catch ( Exception e ) {
62+
e.printStackTrace( System.out );
63+
SSL = 0;
64+
}
65+
}
66+
67+
private void processHandshake() throws IOException {
68+
assert ( res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED );
69+
if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP ) {
70+
// unwrap
71+
if( !sTOc.hasRemaining() )
72+
sTOc.clear();
73+
sc.read( sTOc );
74+
sTOc.flip();
75+
unwrap( sTOc );
76+
if( res.getHandshakeStatus() != SSLEngineResult.HandshakeStatus.FINISHED ) {
77+
clientOut.clear();
78+
sc.write( wrap( clientOut ) );
79+
}
80+
} else if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_WRAP ) {
81+
// wrap
82+
clientOut.clear();
83+
sc.write( wrap( clientOut ) );
84+
} else {
85+
assert ( false );
86+
}
87+
88+
}
89+
90+
private synchronized ByteBuffer wrap( ByteBuffer b ) throws SSLException {
91+
cTOs.clear();
92+
res = sslEngine.wrap( b, cTOs );
93+
cTOs.flip();
94+
return cTOs;
95+
}
96+
97+
private synchronized ByteBuffer unwrap( ByteBuffer b ) throws SSLException {
98+
clientIn.clear();
99+
while ( b.hasRemaining() ) {
100+
res = sslEngine.unwrap( b, clientIn );
101+
if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_TASK ) {
102+
// Task
103+
Runnable task;
104+
while ( ( task = sslEngine.getDelegatedTask() ) != null ) {
105+
task.run();
106+
}
107+
} else if( res.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.FINISHED ) {
108+
return clientIn;
109+
} else if( res.getStatus() == SSLEngineResult.Status.BUFFER_UNDERFLOW ) {
110+
return clientIn;
111+
}
112+
}
113+
return clientIn;
114+
}
115+
116+
private void createBuffers( SSLSession session ) {
117+
int appBufferMax = session.getApplicationBufferSize();
118+
int netBufferMax = session.getPacketBufferSize();
119+
120+
clientIn = ByteBuffer.allocate( 65536 );
121+
clientOut = ByteBuffer.allocate( appBufferMax );
122+
123+
cTOs = ByteBuffer.allocate( netBufferMax );
124+
sTOc = ByteBuffer.allocate( netBufferMax );
125+
}
126+
127+
public int write( ByteBuffer src ) throws IOException {
128+
if( SSL == 4 ) {
129+
return sc.write( wrap( src ) );
130+
}
131+
return sc.write( src );
132+
}
133+
134+
public int read( ByteBuffer dst ) throws IOException {
135+
int amount = 0, limit;
136+
if( SSL == 4 ) {
137+
// test if there was a buffer overflow in dst
138+
if( clientIn.hasRemaining() ) {
139+
limit = Math.min( clientIn.remaining(), dst.remaining() );
140+
for( int i = 0 ; i < limit ; i++ ) {
141+
dst.put( clientIn.get() );
142+
amount++;
143+
}
144+
return amount;
145+
}
146+
// test if some bytes left from last read (e.g. BUFFER_UNDERFLOW)
147+
if( sTOc.hasRemaining() ) {
148+
unwrap( sTOc );
149+
clientIn.flip();
150+
limit = Math.min( clientIn.limit(), dst.remaining() );
151+
for( int i = 0 ; i < limit ; i++ ) {
152+
dst.put( clientIn.get() );
153+
amount++;
154+
}
155+
if( res.getStatus() != SSLEngineResult.Status.BUFFER_UNDERFLOW ) {
156+
sTOc.clear();
157+
sTOc.flip();
158+
return amount;
159+
}
160+
}
161+
if( !sTOc.hasRemaining() )
162+
sTOc.clear();
163+
else
164+
sTOc.compact();
165+
166+
if( sc.read( sTOc ) == -1 ) {
167+
sTOc.clear();
168+
sTOc.flip();
169+
return -1;
170+
}
171+
sTOc.flip();
172+
unwrap( sTOc );
173+
// write in dst
174+
clientIn.flip();
175+
limit = Math.min( clientIn.limit(), dst.remaining() );
176+
for( int i = 0 ; i < limit ; i++ ) {
177+
dst.put( clientIn.get() );
178+
amount++;
179+
}
180+
return amount;
181+
}
182+
return sc.read( dst );
183+
}
184+
185+
public boolean isConnected() {
186+
return sc.isConnected();
187+
}
188+
189+
public void close() throws IOException {
190+
if( SSL == 4 ) {
191+
sslEngine.closeOutbound();
192+
sslEngine.getSession().invalidate();
193+
clientOut.clear();
194+
sc.write( wrap( clientOut ) );
195+
sc.close();
196+
} else
197+
sc.close();
198+
}
199+
200+
public SelectableChannel configureBlocking( boolean b ) throws IOException {
201+
return sc.configureBlocking( b );
202+
}
203+
204+
public boolean connect( SocketAddress remote ) throws IOException {
205+
return sc.connect( remote );
206+
}
207+
208+
public boolean finishConnect() throws IOException {
209+
return sc.finishConnect();
210+
}
211+
212+
public Socket socket() {
213+
return sc.socket();
214+
}
215+
216+
public boolean isInboundDone() {
217+
return sslEngine.isInboundDone();
218+
}
219+
220+
@Override
221+
public boolean isOpen() {
222+
return sc.isOpen();
223+
}
224+
}

src/org/java_websocket/SocketChannelIOHelper.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import org.java_websocket.drafts.Draft;
88

99
public class SocketChannelIOHelper {
10+
11+
private static ByteBuffer emptybuffer = ByteBuffer.allocate( 0 );
1012

1113
public static boolean read( final ByteBuffer buf, WebSocketImpl ws, ByteChannel channel ) throws IOException {
1214
buf.clear();
@@ -21,9 +23,15 @@ public static boolean read( final ByteBuffer buf, WebSocketImpl ws, ByteChannel
2123
return read != 0;
2224
}
2325

26+
/** Returns whether the whole outQueue has been flushed */
2427
public static boolean batch( WebSocketImpl ws, ByteChannel sockchannel ) throws IOException {
2528
ByteBuffer buffer = ws.outQueue.peek();
26-
while ( buffer != null ) {
29+
30+
if( buffer == null ) {
31+
return sockchannel.write( emptybuffer ) == 0;
32+
}
33+
34+
while ( buffer != null ) {// FIXME writing as much as possible is unfair!!
2735
/*int written = */sockchannel.write( buffer );
2836
if( buffer.remaining() > 0 ) {
2937
return false;

src/org/java_websocket/client/WebSocketClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,10 @@ private void finishConnect( SelectionKey key ) throws IOException , InvalidHands
276276
if( channel.isConnectionPending() ) {
277277
channel.finishConnect();
278278
}
279-
wrappedchannel = wf.wrapChannel( key );
280279
// Now that we're connected, re-register for only 'READ' keys.
281280
key.interestOps( SelectionKey.OP_READ );
282281

282+
wrappedchannel = wf.wrapChannel( key );
283283
sendHandshake();
284284
}
285285

0 commit comments

Comments
 (0)