View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.websocket.client.io;
20  
21  import java.io.IOException;
22  import java.nio.channels.SelectionKey;
23  import java.nio.channels.SocketChannel;
24  import java.util.concurrent.Executor;
25  
26  import javax.net.ssl.SSLEngine;
27  
28  import org.eclipse.jetty.io.ByteBufferPool;
29  import org.eclipse.jetty.io.Connection;
30  import org.eclipse.jetty.io.EndPoint;
31  import org.eclipse.jetty.io.ManagedSelector;
32  import org.eclipse.jetty.io.SelectChannelEndPoint;
33  import org.eclipse.jetty.io.SelectorManager;
34  import org.eclipse.jetty.io.ssl.SslConnection;
35  import org.eclipse.jetty.util.log.Log;
36  import org.eclipse.jetty.util.log.Logger;
37  import org.eclipse.jetty.util.ssl.SslContextFactory;
38  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
39  import org.eclipse.jetty.websocket.client.WebSocketClient;
40  
41  public class WebSocketClientSelectorManager extends SelectorManager
42  {
43      private static final Logger LOG = Log.getLogger(WebSocketClientSelectorManager.class);
44      private final WebSocketPolicy policy;
45      private final ByteBufferPool bufferPool;
46      private SslContextFactory sslContextFactory;
47  
48      public WebSocketClientSelectorManager(WebSocketClient client)
49      {
50          super(client.getExecutor(),client.getScheduler());
51          this.bufferPool = client.getBufferPool();
52          this.policy = client.getPolicy();
53      }
54  
55      @Override
56      protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
57      {
58          if (LOG.isDebugEnabled())
59              LOG.debug("Connection Failed",ex);
60          ConnectPromise connect = (ConnectPromise)attachment;
61          connect.failed(ex);
62      }
63  
64      public SslContextFactory getSslContextFactory()
65      {
66          return sslContextFactory;
67      }
68  
69      @Override
70      public Connection newConnection(final SocketChannel channel, EndPoint endPoint, final Object attachment) throws IOException
71      {
72          if (LOG.isDebugEnabled())
73              LOG.debug("newConnection({},{},{})",channel,endPoint,attachment);
74          ConnectPromise connectPromise = (ConnectPromise)attachment;
75  
76          try
77          {
78              String scheme = connectPromise.getRequest().getRequestURI().getScheme();
79  
80              if ("wss".equalsIgnoreCase(scheme))
81              {
82                  // Encrypted "wss://"
83                  SslContextFactory sslContextFactory = getSslContextFactory();
84                  if (sslContextFactory != null)
85                  {
86                      SSLEngine engine = newSSLEngine(sslContextFactory,channel);
87                      SslConnection sslConnection = new SslConnection(bufferPool,getExecutor(),endPoint,engine);
88                      sslConnection.setRenegotiationAllowed(sslContextFactory.isRenegotiationAllowed());
89                      EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
90  
91                      Connection connection = newUpgradeConnection(channel,sslEndPoint,connectPromise);
92                      sslEndPoint.setIdleTimeout(connectPromise.getClient().getMaxIdleTimeout());
93                      sslEndPoint.setConnection(connection);
94                      return sslConnection;
95                  }
96                  else
97                  {
98                      throw new IOException("Cannot init SSL");
99                  }
100             }
101             else
102             {
103                 // Standard "ws://"
104                 endPoint.setIdleTimeout(connectPromise.getDriver().getPolicy().getIdleTimeout());
105                 return newUpgradeConnection(channel,endPoint,connectPromise);
106             }
107         }
108         catch (IOException e)
109         {
110             LOG.ignore(e);
111             connectPromise.failed(e);
112             // rethrow
113             throw e;
114         }
115     }
116 
117     @Override
118     protected EndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey selectionKey) throws IOException
119     {
120         if (LOG.isDebugEnabled())
121             LOG.debug("newEndPoint({}, {}, {})",channel,selectSet,selectionKey);
122         return new SelectChannelEndPoint(channel,selectSet,selectionKey,getScheduler(),policy.getIdleTimeout());
123     }
124 
125     public SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
126     {
127         String peerHost = channel.socket().getInetAddress().getHostName();
128         int peerPort = channel.socket().getPort();
129         SSLEngine engine = sslContextFactory.newSSLEngine(peerHost,peerPort);
130         engine.setUseClientMode(true);
131         return engine;
132     }
133 
134     public UpgradeConnection newUpgradeConnection(SocketChannel channel, EndPoint endPoint, ConnectPromise connectPromise)
135     {
136         WebSocketClient client = connectPromise.getClient();
137         Executor executor = client.getExecutor();
138         UpgradeConnection connection = new UpgradeConnection(endPoint,executor,connectPromise);
139         return connection;
140     }
141 
142     public void setSslContextFactory(SslContextFactory sslContextFactory)
143     {
144         this.sslContextFactory = sslContextFactory;
145     }
146     
147     public WebSocketPolicy getPolicy()
148     {
149         return policy;
150     }
151 }