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.util.thread.Scheduler;
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(ByteBufferPool bufferPool, Executor executor, Scheduler scheduler, WebSocketPolicy policy)
49      {
50          super(executor,scheduler);
51          this.bufferPool = bufferPool;
52          this.policy = policy;
53      }
54  
55      @Override
56      protected void connectionFailed(SocketChannel channel, Throwable ex, Object attachment)
57      {
58          LOG.info("Connection Failed",ex);
59          ConnectPromise connect = (ConnectPromise)attachment;
60          connect.failed(ex);
61      }
62  
63      public SslContextFactory getSslContextFactory()
64      {
65          return sslContextFactory;
66      }
67  
68      @Override
69      public Connection newConnection(final SocketChannel channel, EndPoint endPoint, final Object attachment) throws IOException
70      {
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                      EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
87  
88                      Connection connection = newUpgradeConnection(channel,sslEndPoint,connectPromise);
89                      sslEndPoint.setIdleTimeout(connectPromise.getClient().getMaxIdleTimeout());
90                      sslEndPoint.setConnection(connection);
91                      connectionOpened(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.getClient().getMaxIdleTimeout());
103                 return newUpgradeConnection(channel,endPoint,connectPromise);
104             }
105         }
106         catch (IOException e)
107         {
108             LOG.debug(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         LOG.debug("newEndPoint({}, {}, {})",channel,selectSet,selectionKey);
119         return new SelectChannelEndPoint(channel,selectSet,selectionKey,getScheduler(),policy.getIdleTimeout());
120     }
121 
122     public SSLEngine newSSLEngine(SslContextFactory sslContextFactory, SocketChannel channel)
123     {
124         String peerHost = channel.socket().getInetAddress().getHostAddress();
125         int peerPort = channel.socket().getPort();
126         SSLEngine engine = sslContextFactory.newSSLEngine(peerHost,peerPort);
127         engine.setUseClientMode(true);
128         return engine;
129     }
130 
131     public UpgradeConnection newUpgradeConnection(SocketChannel channel, EndPoint endPoint, ConnectPromise connectPromise)
132     {
133         WebSocketClient client = connectPromise.getClient();
134         Executor executor = client.getExecutor();
135         UpgradeConnection connection = new UpgradeConnection(endPoint,executor,connectPromise);
136         return connection;
137     }
138 
139     public void setSslContextFactory(SslContextFactory sslContextFactory)
140     {
141         this.sslContextFactory = sslContextFactory;
142     }
143 }