View Javadoc

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