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