View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 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  import javax.net.ssl.SSLEngine;
26  
27  import org.eclipse.jetty.io.ByteBufferPool;
28  import org.eclipse.jetty.io.Connection;
29  import org.eclipse.jetty.io.EndPoint;
30  import org.eclipse.jetty.io.SelectChannelEndPoint;
31  import org.eclipse.jetty.io.SelectorManager;
32  import org.eclipse.jetty.io.ssl.SslConnection;
33  import org.eclipse.jetty.util.log.Log;
34  import org.eclipse.jetty.util.log.Logger;
35  import org.eclipse.jetty.util.ssl.SslContextFactory;
36  import org.eclipse.jetty.websocket.api.WebSocketPolicy;
37  import org.eclipse.jetty.websocket.client.WebSocketClient;
38  
39  public class WebSocketClientSelectorManager extends SelectorManager
40  {
41      private static final Logger LOG = Log.getLogger(WebSocketClientSelectorManager.class);
42      private final WebSocketPolicy policy;
43      private final ByteBufferPool bufferPool;
44      private SslContextFactory sslContextFactory;
45  
46      public WebSocketClientSelectorManager(WebSocketClient client)
47      {
48          super(client.getExecutor(),client.getScheduler());
49          this.bufferPool = client.getBufferPool();
50          this.policy = client.getPolicy();
51      }
52  
53      @Override
54      protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
55      {
56          if (LOG.isDebugEnabled())
57              LOG.debug("Connection Failed",ex);
58          ConnectPromise connect = (ConnectPromise)attachment;
59          connect.failed(ex);
60      }
61  
62      public SslContextFactory getSslContextFactory()
63      {
64          return sslContextFactory;
65      }
66  
67      @Override
68      public Connection newConnection(final SocketChannel channel, EndPoint endPoint, final Object attachment) throws IOException
69      {
70          if (LOG.isDebugEnabled())
71              LOG.debug("newConnection({},{},{})",channel,endPoint,attachment);
72          ConnectPromise connectPromise = (ConnectPromise)attachment;
73  
74          try
75          {
76              String scheme = connectPromise.getRequest().getRequestURI().getScheme();
77  
78              if ("wss".equalsIgnoreCase(scheme))
79              {
80                  // Encrypted "wss://"
81                  SslContextFactory sslContextFactory = getSslContextFactory();
82                  if (sslContextFactory != null)
83                  {
84                      SSLEngine engine = newSSLEngine(sslContextFactory,channel);
85                      SslConnection sslConnection = new SslConnection(bufferPool,getExecutor(),endPoint,engine);
86                      sslConnection.setRenegotiationAllowed(sslContextFactory.isRenegotiationAllowed());
87                      EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
88  
89                      Connection connection = newUpgradeConnection(channel,sslEndPoint,connectPromise);
90                      sslEndPoint.setIdleTimeout(connectPromise.getClient().getMaxIdleTimeout());
91                      sslEndPoint.setConnection(connection);
92                      return sslConnection;
93                  }
94                  else
95                  {
96                      throw new IOException("Cannot init SSL");
97                  }
98              }
99              else
100             {
101                 // Standard "ws://"
102                 endPoint.setIdleTimeout(connectPromise.getDriver().getPolicy().getIdleTimeout());
103                 return newUpgradeConnection(channel,endPoint,connectPromise);
104             }
105         }
106         catch (IOException e)
107         {
108             LOG.ignore(e);
109             connectPromise.failed(e);
110             // rethrow
111             throw e;
112         }
113     }
114 
115     @Override
116     protected EndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey selectionKey) throws IOException
117     {
118         if (LOG.isDebugEnabled())
119             LOG.debug("newEndPoint({}, {}, {})",channel,selectSet,selectionKey);
120         return new SelectChannelEndPoint(channel,selectSet,selectionKey,getScheduler(),policy.getIdleTimeout());
121     }
122 
123     public SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
124     {
125         String peerHost = channel.socket().getInetAddress().getHostName();
126         int peerPort = channel.socket().getPort();
127         SSLEngine engine = sslContextFactory.newSSLEngine(peerHost,peerPort);
128         engine.setUseClientMode(true);
129         return engine;
130     }
131 
132     public UpgradeConnection newUpgradeConnection(SocketChannel channel, EndPoint endPoint, ConnectPromise connectPromise)
133     {
134         WebSocketClient client = connectPromise.getClient();
135         Executor executor = client.getExecutor();
136         UpgradeConnection connection = new UpgradeConnection(endPoint,executor,connectPromise);
137         return connection;
138     }
139 
140     public void setSslContextFactory(SslContextFactory sslContextFactory)
141     {
142         this.sslContextFactory = sslContextFactory;
143     }
144     
145     public WebSocketPolicy getPolicy()
146     {
147         return policy;
148     }
149 }