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.io;
20  
21  import java.io.IOException;
22  import java.util.Map;
23  import java.util.concurrent.Executor;
24  
25  import javax.net.ssl.SSLEngine;
26  
27  import org.eclipse.jetty.util.BufferUtil;
28  import org.eclipse.jetty.util.log.Log;
29  import org.eclipse.jetty.util.log.Logger;
30  
31  public abstract class NegotiatingClientConnection extends AbstractConnection
32  {
33      private static final Logger LOG = Log.getLogger(NegotiatingClientConnection.class);
34  
35      private final SSLEngine engine;
36      private final ClientConnectionFactory connectionFactory;
37      private final Map<String, Object> context;
38      private volatile boolean completed;
39  
40      protected NegotiatingClientConnection(EndPoint endp, Executor executor, SSLEngine sslEngine, ClientConnectionFactory connectionFactory, Map<String, Object> context)
41      {
42          super(endp, executor);
43          this.engine = sslEngine;
44          this.connectionFactory = connectionFactory;
45          this.context = context;
46      }
47  
48      protected SSLEngine getSSLEngine()
49      {
50          return engine;
51      }
52  
53      protected void completed()
54      {
55          completed = true;
56      }
57  
58      @Override
59      public void onOpen()
60      {
61          super.onOpen();
62          try
63          {
64              getEndPoint().flush(BufferUtil.EMPTY_BUFFER);
65              if (completed)
66                  replaceConnection();
67              else
68                  fillInterested();
69          }
70          catch (IOException x)
71          {
72              close();
73              throw new RuntimeIOException(x);
74          }
75      }
76  
77      @Override
78      public void onFillable()
79      {
80          while (true)
81          {
82              int filled = fill();
83              if (filled == 0 && !completed)
84                  fillInterested();
85              if (filled <= 0 || completed)
86                  break;
87          }
88          if (completed)
89              replaceConnection();
90      }
91  
92      private int fill()
93      {
94          try
95          {
96              return getEndPoint().fill(BufferUtil.EMPTY_BUFFER);
97          }
98          catch (IOException x)
99          {
100             LOG.debug(x);
101             close();
102             return -1;
103         }
104     }
105 
106     private void replaceConnection()
107     {
108         EndPoint endPoint = getEndPoint();
109         try
110         {
111             endPoint.upgrade(connectionFactory.newConnection(endPoint, context));
112         }
113         catch (Throwable x)
114         {
115             LOG.debug(x);
116             close();
117         }
118     }
119 
120     @Override
121     public void close()
122     {
123         // Gentler close for SSL.
124         getEndPoint().shutdownOutput();
125         super.close();
126     }
127 }