Skip to content

Commit 76d1206

Browse files
committed
worked on proxy support #88
1 parent 787acc8 commit 76d1206

File tree

4 files changed

+186
-30
lines changed

4 files changed

+186
-30
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import java.net.InetSocketAddress;
2+
import java.net.URI;
3+
import java.net.URISyntaxException;
4+
import java.nio.channels.ByteChannel;
5+
6+
public class ProxyClientExample extends ExampleClient {
7+
8+
public ProxyClientExample( URI serverURI , InetSocketAddress proxy ) {
9+
super( serverURI );
10+
setProxy( proxy );
11+
}
12+
13+
@Override
14+
public ByteChannel createProxyChannel( ByteChannel towrap ) {
15+
/*
16+
* You can create custom proxy handshake here.
17+
* For more infos see: WebSocketClient.DefaultClientProxyChannel and http://tools.ietf.org/html/rfc6455#section-4.1
18+
*/
19+
return super.createProxyChannel( towrap );
20+
}
21+
22+
public static void main( String[] args ) throws URISyntaxException {
23+
ProxyClientExample c = new ProxyClientExample( new URI( "ws://echo.websocket.org" ), new InetSocketAddress( "proxyaddress", 80 ) );// don't forget to change "proxyaddress"
24+
c.connect();
25+
}
26+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package org.java_websocket;
2+
3+
import java.io.IOException;
4+
import java.nio.ByteBuffer;
5+
import java.nio.channels.ByteChannel;
6+
import java.nio.channels.SocketChannel;
7+
8+
import javax.net.ssl.SSLException;
9+
10+
11+
public class AbstractWrappedByteChannel implements WrappedByteChannel {
12+
13+
private final ByteChannel channel;
14+
15+
public AbstractWrappedByteChannel( ByteChannel towrap ) {
16+
this.channel = towrap;
17+
}
18+
19+
public AbstractWrappedByteChannel( WrappedByteChannel towrap ) {
20+
this.channel = towrap;
21+
}
22+
23+
@Override
24+
public int read( ByteBuffer dst ) throws IOException {
25+
return channel.read( dst );
26+
}
27+
28+
@Override
29+
public boolean isOpen() {
30+
return channel.isOpen();
31+
}
32+
33+
@Override
34+
public void close() throws IOException {
35+
channel.close();
36+
}
37+
38+
@Override
39+
public int write( ByteBuffer src ) throws IOException {
40+
return channel.write( src );
41+
}
42+
43+
@Override
44+
public boolean isNeedWrite() {
45+
return channel instanceof WrappedByteChannel ? ( (WrappedByteChannel) channel ).isNeedWrite() : false;
46+
}
47+
48+
@Override
49+
public void writeMore() throws IOException {
50+
if( channel instanceof WrappedByteChannel )
51+
( (WrappedByteChannel) channel ).writeMore();
52+
53+
}
54+
55+
@Override
56+
public boolean isNeedRead() {
57+
return channel instanceof WrappedByteChannel ? ( (WrappedByteChannel) channel ).isNeedRead() : false;
58+
59+
}
60+
61+
@Override
62+
public int readMore( ByteBuffer dst ) throws SSLException {
63+
return channel instanceof WrappedByteChannel ? ( (WrappedByteChannel) channel ).readMore( dst ) : 0;
64+
}
65+
66+
@Override
67+
public boolean isBlocking() {
68+
if( channel instanceof SocketChannel )
69+
return ( (SocketChannel) channel ).isBlocking();
70+
else if( channel instanceof WrappedByteChannel )
71+
return ( (WrappedByteChannel) channel ).isBlocking();
72+
return false;
73+
}
74+
75+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package org.java_websocket.client;
2+
3+
import java.io.IOException;
4+
import java.io.UnsupportedEncodingException;
5+
import java.nio.ByteBuffer;
6+
import java.nio.channels.ByteChannel;
7+
8+
import org.java_websocket.AbstractWrappedByteChannel;
9+
10+
public abstract class AbstractClientProxyChannel extends AbstractWrappedByteChannel {
11+
protected final ByteBuffer proxyHandshake;
12+
13+
14+
/**
15+
* @param towrap
16+
* The channel to the proxy server
17+
**/
18+
public AbstractClientProxyChannel( ByteChannel towrap ) {
19+
super( towrap );
20+
try {
21+
proxyHandshake = ByteBuffer.wrap( buildHandShake().getBytes( "ASCII" ) );
22+
} catch ( UnsupportedEncodingException e ) {
23+
throw new RuntimeException( e );
24+
}
25+
}
26+
27+
@Override
28+
public int write( ByteBuffer src ) throws IOException {
29+
if( !proxyHandshake.hasRemaining() ) {
30+
return super.write( src );
31+
} else {
32+
return super.write( proxyHandshake );
33+
}
34+
}
35+
36+
public abstract String buildHandShake();
37+
38+
}

src/main/java/org/java_websocket/client/WebSocketClient.java

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import java.io.IOException;
44
import java.net.InetSocketAddress;
5-
import java.net.Socket;
65
import java.net.URI;
76
import java.nio.ByteBuffer;
87
import java.nio.channels.ByteChannel;
@@ -12,7 +11,6 @@
1211
import java.nio.channels.SelectionKey;
1312
import java.nio.channels.SocketChannel;
1413
import java.nio.channels.spi.SelectorProvider;
15-
import java.util.List;
1614
import java.util.Map;
1715
import java.util.concurrent.CountDownLatch;
1816

@@ -46,7 +44,7 @@ public abstract class WebSocketClient extends WebSocketAdapter implements Runnab
4644
/**
4745
* The URI this channel is supposed to connect to.
4846
*/
49-
private URI uri = null;
47+
protected URI uri = null;
5048

5149
private WebSocketImpl conn = null;
5250
/**
@@ -70,24 +68,9 @@ public abstract class WebSocketClient extends WebSocketAdapter implements Runnab
7068

7169
private int timeout = 0;
7270

73-
WebSocketClientFactory wsfactory = new WebSocketClientFactory() {
74-
@Override
75-
public WebSocket createWebSocket( WebSocketAdapter a, Draft d, Socket s ) {
76-
return new WebSocketImpl( WebSocketClient.this, d );
77-
}
71+
private WebSocketClientFactory wsfactory = new DefaultWebSocketClientFactory( this );
7872

79-
@Override
80-
public WebSocket createWebSocket( WebSocketAdapter a, List<Draft> d, Socket s ) {
81-
return new WebSocketImpl( WebSocketClient.this, d );
82-
}
83-
84-
@Override
85-
public ByteChannel wrapChannel( SocketChannel channel, SelectionKey c, String host, int port ) {
86-
if( c == null )
87-
return channel;
88-
return channel;
89-
}
90-
};
73+
private InetSocketAddress proxyAddress = null;
9174

9275
public WebSocketClient( URI serverURI ) {
9376
this( serverURI, new Draft_10() );
@@ -198,12 +181,6 @@ public void send( byte[] data ) throws NotYetConnectedException {
198181
conn.send( data );
199182
}
200183

201-
private void tryToConnect( InetSocketAddress remote ) throws IOException , InvalidHandshakeException {
202-
203-
channel.connect( remote );
204-
205-
}
206-
207184
// Runnable IMPLEMENTATION /////////////////////////////////////////////////
208185
public void run() {
209186
if( writethread == null )
@@ -220,10 +197,19 @@ private final void interruptableRun() {
220197
}
221198

222199
try {
223-
String host = uri.getHost();
224-
int port = getPort();
225-
tryToConnect( new InetSocketAddress( host, port ) );
226-
conn.channel = wrappedchannel = wsfactory.wrapChannel( channel, null, host, port );
200+
String host;
201+
int port ;
202+
203+
if( proxyAddress != null ) {
204+
host = proxyAddress.getHostName();
205+
port = proxyAddress.getPort();
206+
} else {
207+
host = uri.getHost();
208+
port = getPort();
209+
}
210+
channel.connect( new InetSocketAddress( host, port ) );
211+
conn.channel = wrappedchannel = createProxyChannel( wsfactory.wrapChannel( channel, null, host, port ) );
212+
227213
timeout = 0; // since connect is over
228214
sendHandshake();
229215
readthread = new Thread( new WebsocketWriteThread() );
@@ -420,6 +406,26 @@ public InetSocketAddress getRemoteSocketAddress( WebSocket conn ) {
420406
public void onMessage( ByteBuffer bytes ) {
421407
};
422408

409+
public class DefaultClientProxyChannel extends AbstractClientProxyChannel {
410+
public DefaultClientProxyChannel( ByteChannel towrap ) {
411+
super( towrap );
412+
}
413+
@Override
414+
public String buildHandShake() {
415+
StringBuilder b = new StringBuilder();
416+
String host = uri.getHost();
417+
b.append( "CONNECT " );
418+
b.append( host );
419+
b.append( ":" );
420+
b.append( getPort() );
421+
b.append( " HTTP/1.1\n" );
422+
b.append( "Host: " );
423+
b.append( host );
424+
b.append( "\n" );
425+
return b.toString();
426+
}
427+
}
428+
423429
public interface WebSocketClientFactory extends WebSocketFactory {
424430
public ByteChannel wrapChannel( SocketChannel channel, SelectionKey key, String host, int port ) throws IOException;
425431
}
@@ -439,4 +445,15 @@ public void run() {
439445
}
440446
}
441447
}
448+
449+
public ByteChannel createProxyChannel( ByteChannel towrap ) {
450+
if( proxyAddress != null ){
451+
return new DefaultClientProxyChannel( towrap );
452+
}
453+
return towrap;//no proxy in use
454+
}
455+
456+
public void setProxy( InetSocketAddress proxyaddress ) {
457+
proxyAddress = proxyaddress;
458+
}
442459
}

0 commit comments

Comments
 (0)