View | Details | Raw Unified | Return to bug 55006
Collapse All | Expand All

(-)java/org/apache/tomcat/websocket/LocalStrings.properties (+2 lines)
Lines 77-79 Link Here
77
wsWebSocketContainer.pathNoHost=No host was specified in URI
77
wsWebSocketContainer.pathNoHost=No host was specified in URI
78
wsWebSocketContainer.pathWrongScheme=The scheme [{0}] is not supported
78
wsWebSocketContainer.pathWrongScheme=The scheme [{0}] is not supported
79
wsWebSocketContainer.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections
79
wsWebSocketContainer.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections
80
wsWebSocketContainer.invalidProxy=Specified proxy [{0}] configuration is invalid
81
wsWebSocketContainer.proxyConnection=Client is unable to connect to proxy [{0}]
(-)java/org/apache/tomcat/websocket/WsWebSocketContainer.java (-26 / +108 lines)
Lines 22-32 Link Here
22
import java.io.IOException;
22
import java.io.IOException;
23
import java.io.InputStream;
23
import java.io.InputStream;
24
import java.net.InetSocketAddress;
24
import java.net.InetSocketAddress;
25
import java.net.Proxy;
26
import java.net.ProxySelector;
25
import java.net.SocketAddress;
27
import java.net.SocketAddress;
26
import java.net.URI;
28
import java.net.URI;
29
import java.net.URISyntaxException;
27
import java.nio.ByteBuffer;
30
import java.nio.ByteBuffer;
28
import java.nio.channels.AsynchronousChannelGroup;
31
import java.nio.channels.AsynchronousChannelGroup;
29
import java.nio.channels.AsynchronousSocketChannel;
32
import java.nio.channels.AsynchronousSocketChannel;
33
import java.nio.channels.UnresolvedAddressException;
30
import java.nio.charset.Charset;
34
import java.nio.charset.Charset;
31
import java.security.KeyStore;
35
import java.security.KeyStore;
32
import java.util.ArrayList;
36
import java.util.ArrayList;
Lines 249-280 Link Here
249
                    sm.getString("wsWebSocketContainer.pathNoHost"));
253
                    sm.getString("wsWebSocketContainer.pathNoHost"));
250
        }
254
        }
251
        int port = path.getPort();
255
        int port = path.getPort();
256
        List<Proxy> proxies = null;
257
        
258
        if ("ws".equalsIgnoreCase(scheme)){
259
            if (port == -1) port = 80;
260
        	try {
261
				proxies = ProxySelector.getDefault().select(new URI("http://"+host+":"+port));
262
			} catch (URISyntaxException e) {
263
				throw new DeploymentException(
264
                        sm.getString("wsWebSocketContainer.invalidScheme"));
265
			}
266
        } else if ("wss".equalsIgnoreCase(scheme)){
267
        		secure = true;
268
        		if (port == -1) port = 443;
269
        		try {
270
					proxies = ProxySelector.getDefault().select(new URI("https://"+host+":"+port));
271
				} catch (URISyntaxException e) {
272
					throw new DeploymentException(
273
	                        sm.getString("wsWebSocketContainer.invalidScheme"));
274
				}
275
        } else{
276
        		//we shouldn't be here as the scheme is already checked above
277
        		 throw new DeploymentException(
278
                         sm.getString("wsWebSocketContainer.invalidScheme"));
279
        }
252
        Map<String,List<String>> reqHeaders = createRequestHeaders(host, port,
280
        Map<String,List<String>> reqHeaders = createRequestHeaders(host, port,
253
                clientEndpointConfiguration.getPreferredSubprotocols());
281
                clientEndpointConfiguration.getPreferredSubprotocols());
254
        clientEndpointConfiguration.getConfigurator().
282
        clientEndpointConfiguration.getConfigurator().
255
                beforeRequest(reqHeaders);
283
                beforeRequest(reqHeaders);
256
284
        
285
        //construct initial HTTP GET request
257
        ByteBuffer request = createRequest(path, reqHeaders);
286
        ByteBuffer request = createRequest(path, reqHeaders);
258
287
        ByteBuffer proxyConnectRequest = null;
259
        SocketAddress sa;
288
        
260
        if (port == -1) {
289
          AsynchronousSocketChannel socketChannel;
261
            if ("ws".equalsIgnoreCase(scheme)) {
262
                sa = new InetSocketAddress(host, 80);
263
            } else if ("wss".equalsIgnoreCase(scheme)) {
264
                sa = new InetSocketAddress(host, 443);
265
                secure = true;
266
            } else {
267
                throw new DeploymentException(
268
                        sm.getString("wsWebSocketContainer.invalidScheme"));
269
            }
270
        } else {
271
            if ("wss".equalsIgnoreCase(scheme)) {
272
                secure = true;
273
            }
274
            sa = new InetSocketAddress(host, port);
275
        }
276
277
        AsynchronousSocketChannel socketChannel;
278
        try {
290
        try {
279
            socketChannel =
291
            socketChannel =
280
                    AsynchronousSocketChannel.open(asynchronousChannelGroup);
292
                    AsynchronousSocketChannel.open(asynchronousChannelGroup);
Lines 282-290 Link Here
282
            throw new DeploymentException(sm.getString(
294
            throw new DeploymentException(sm.getString(
283
                    "wsWebSocketContainer.asynchronousSocketChannelFail"), ioe);
295
                    "wsWebSocketContainer.asynchronousSocketChannelFail"), ioe);
284
        }
296
        }
297
        
298
        
299
        boolean proxyIsSet = false;
300
        SocketAddress sa = new InetSocketAddress(host, port);
301
        
302
        if (proxies != null){
303
		  for (Proxy p : proxies) {
304
			if (p.type().equals(Proxy.Type.HTTP)) {
285
305
286
        Future<Void> fConnect = socketChannel.connect(sa);
306
				sa = proxies.get(0).address();
287
307
				String[] split = sa.toString().split(":");
308
				if ((split.length < 2) || split[0] == null || split[1] == null) {
309
					proxyIsSet = false;
310
					throw new DeploymentException(sm.getString("wsWebSocketContainer.invalidProxy",p.toString()));
311
				}
312
				sa = new InetSocketAddress(split[0], Integer.valueOf(split[1]));
313
				proxyConnectRequest = createProxyConnect(host, port);
314
				try {
315
					Future<Void> fConnect = socketChannel.connect(sa);
316
					if (fConnect.get() == null) {
317
						proxyIsSet = true;
318
						break;
319
					}
320
				} catch (InterruptedException | ExecutionException | UnresolvedAddressException e) {
321
					try {
322
						ProxySelector.getDefault().connectFailed(new URI(host + ":" + Integer.valueOf(port)),
323
									sa, new IOException(e));
324
					} catch (URISyntaxException e1) {
325
						throw new DeploymentException(sm.getString("wsWebSocketContainer.invalidProxy",p.toString()),e1);
326
					}
327
					throw new DeploymentException(sm.getString("wsWebSocketContainer.proxyConnection",p.toString()),e);
328
				}
329
			}
330
		  }
331
        }
332
        
333
        try {
334
            //if we are behind the proxy lets't do initial CONNECT
335
            if (proxyIsSet && proxyConnectRequest != null){
336
        		while (proxyConnectRequest.hasRemaining()){
337
					Future<Integer>fwrite = socketChannel.write(proxyConnectRequest);
338
					fwrite.get();
339
					proxyConnectRequest.compact();
340
					proxyConnectRequest.flip();
341
				}
342
        		//let's read the response
343
        	    proxyConnectRequest.clear();
344
        	    socketChannel.read(proxyConnectRequest).get();
345
			    proxyConnectRequest.flip();
346
            }else{
347
            	//proxy is not set
348
            	 socketChannel.connect(sa).get();
349
            }
350
		} catch (InterruptedException | ExecutionException | UnresolvedAddressException e) {
351
			throw new DeploymentException(
352
	           sm.getString("wsWebSocketContainer.httpRequestFailed"), e);
353
		}
354
        	
288
        AsyncChannelWrapper channel;
355
        AsyncChannelWrapper channel;
289
        if (secure) {
356
        if (secure) {
290
            SSLEngine sslEngine = createSSLEngine(
357
            SSLEngine sslEngine = createSSLEngine(
Lines 297-304 Link Here
297
        ByteBuffer response;
364
        ByteBuffer response;
298
        String subProtocol;
365
        String subProtocol;
299
        try {
366
        try {
300
            fConnect.get();
301
302
            Future<Void> fHandshake = channel.handshake();
367
            Future<Void> fHandshake = channel.handshake();
303
            fHandshake.get();
368
            fHandshake.get();
304
369
Lines 360-366 Link Here
360
    }
425
    }
361
426
362
427
363
    protected void registerSession(Class<?> endpoint, WsSession wsSession) {
428
    private ByteBuffer createProxyConnect(String host, int port) {
429
        //behind the proxy ('should send CONNECT request')
430
    	
431
        ByteBuffer proxyRequest = ByteBuffer.allocate(4 * 1024);
432
   	    proxyRequest.put(("CONNECT "+host+":"+port+" HTTP/1.1").getBytes(iso88591));
433
   	    proxyRequest.put(crlf);
434
   	    proxyRequest.put(("Host: "+host).getBytes(iso88591));
435
   	    proxyRequest.put(crlf);
436
   	    proxyRequest.put("Proxy-Connection: keep-alive".getBytes(iso88591));
437
   	    proxyRequest.put(crlf);
438
   	    
439
   	    proxyRequest.put(crlf);
440
   	    proxyRequest.flip();
441
		return proxyRequest;
442
	}
443
444
445
	protected void registerSession(Class<?> endpoint, WsSession wsSession) {
364
        if (!wsSession.isOpen()) {
446
        if (!wsSession.isOpen()) {
365
            // The session was closed during onOpen. No need to register it.
447
            // The session was closed during onOpen. No need to register it.
366
            return;
448
            return;

Return to bug 55006