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.ssl;
20  
21  import java.io.IOException;
22  import java.nio.ByteBuffer;
23  import java.nio.channels.ClosedChannelException;
24  import java.util.Arrays;
25  import java.util.concurrent.Executor;
26  import javax.net.ssl.SSLEngine;
27  import javax.net.ssl.SSLEngineResult;
28  import javax.net.ssl.SSLEngineResult.HandshakeStatus;
29  import javax.net.ssl.SSLEngineResult.Status;
30  import javax.net.ssl.SSLException;
31  
32  import org.eclipse.jetty.io.AbstractConnection;
33  import org.eclipse.jetty.io.AbstractEndPoint;
34  import org.eclipse.jetty.io.ByteBufferPool;
35  import org.eclipse.jetty.io.Connection;
36  import org.eclipse.jetty.io.EndPoint;
37  import org.eclipse.jetty.io.EofException;
38  import org.eclipse.jetty.io.FillInterest;
39  import org.eclipse.jetty.io.RuntimeIOException;
40  import org.eclipse.jetty.io.SelectChannelEndPoint;
41  import org.eclipse.jetty.io.WriteFlusher;
42  import org.eclipse.jetty.util.BufferUtil;
43  import org.eclipse.jetty.util.Callback;
44  import org.eclipse.jetty.util.log.Log;
45  import org.eclipse.jetty.util.log.Logger;
46  
47  /**
48   * A Connection that acts as an interceptor between an EndPoint providing SSL encrypted data
49   * and another consumer of an EndPoint (typically an {@link Connection} like HttpConnection) that
50   * wants unencrypted data.
51   * <p>
52   * The connector uses an {@link EndPoint} (typically {@link SelectChannelEndPoint}) as
53   * it's source/sink of encrypted data.   It then provides an endpoint via {@link #getDecryptedEndPoint()} to
54   * expose a source/sink of unencrypted data to another connection (eg HttpConnection).
55   * <p>
56   * The design of this class is based on a clear separation between the passive methods, which do not block nor schedule any
57   * asynchronous callbacks, and active methods that do schedule asynchronous callbacks.
58   * <p>
59   * The passive methods are {@link DecryptedEndPoint#fill(ByteBuffer)} and {@link DecryptedEndPoint#flush(ByteBuffer...)}. They make best
60   * effort attempts to progress the connection using only calls to the encrypted {@link EndPoint#fill(ByteBuffer)} and {@link EndPoint#flush(ByteBuffer...)}
61   * methods.  They will never block nor schedule any readInterest or write callbacks.   If a fill/flush cannot progress either because
62   * of network congestion or waiting for an SSL handshake message, then the fill/flush will simply return with zero bytes filled/flushed.
63   * Specifically, if a flush cannot proceed because it needs to receive a handshake message, then the flush will attempt to fill bytes from the
64   * encrypted endpoint, but if insufficient bytes are read it will NOT call {@link EndPoint#fillInterested(Callback)}.
65   * <p>
66   * It is only the active methods : {@link DecryptedEndPoint#fillInterested(Callback)} and
67   * {@link DecryptedEndPoint#write(Callback, ByteBuffer...)} that may schedule callbacks by calling the encrypted
68   * {@link EndPoint#fillInterested(Callback)} and {@link EndPoint#write(Callback, ByteBuffer...)}
69   * methods.  For normal data handling, the decrypted fillInterest method will result in an encrypted fillInterest and a decrypted
70   * write will result in an encrypted write. However, due to SSL handshaking requirements, it is also possible for a decrypted fill
71   * to call the encrypted write and for the decrypted flush to call the encrypted fillInterested methods.
72   * <p>
73   * MOST IMPORTANTLY, the encrypted callbacks from the active methods (#onFillable() and WriteFlusher#completeWrite()) do no filling or flushing
74   * themselves.  Instead they simple make the callbacks to the decrypted callbacks, so that the passive encrypted fill/flush will
75   * be called again and make another best effort attempt to progress the connection.
76   *
77   */
78  public class SslConnection extends AbstractConnection
79  {
80      private static final Logger LOG = Log.getLogger(SslConnection.class);
81      private static final boolean DEBUG = LOG.isDebugEnabled(); // Easy for the compiler to remove the code if DEBUG==false
82      private static final ByteBuffer __FILL_CALLED_FLUSH= BufferUtil.allocate(0);
83      private static final ByteBuffer __FLUSH_CALLED_FILL= BufferUtil.allocate(0);
84      private final ByteBufferPool _bufferPool;
85      private final SSLEngine _sslEngine;
86      private final DecryptedEndPoint _decryptedEndPoint;
87      private ByteBuffer _decryptedInput;
88      private ByteBuffer _encryptedInput;
89      private ByteBuffer _encryptedOutput;
90      private final boolean _encryptedDirectBuffers = false;
91      private final boolean _decryptedDirectBuffers = false;
92      private final Runnable _runCompletWrite = new Runnable()
93      {
94          @Override
95          public void run()
96          {
97              _decryptedEndPoint.getWriteFlusher().completeWrite();
98          }
99      };
100     private boolean _renegotiationAllowed;
101 
102     public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
103     {
104         // This connection does not execute calls to onfillable, so they will be called by the selector thread.
105         // onfillable does not block and will only wakeup another thread to do the actual reading and handling.
106         super(endPoint, executor, !EXECUTE_ONFILLABLE);
107         this._bufferPool = byteBufferPool;
108         this._sslEngine = sslEngine;
109         this._decryptedEndPoint = newDecryptedEndPoint();
110     }
111 
112     protected DecryptedEndPoint newDecryptedEndPoint()
113     {
114         return new DecryptedEndPoint();
115     }
116 
117     public SSLEngine getSSLEngine()
118     {
119         return _sslEngine;
120     }
121 
122     public DecryptedEndPoint getDecryptedEndPoint()
123     {
124         return _decryptedEndPoint;
125     }
126 
127     public boolean isRenegotiationAllowed()
128     {
129         return _renegotiationAllowed;
130     }
131 
132     public void setRenegotiationAllowed(boolean renegotiationAllowed)
133     {
134         this._renegotiationAllowed = renegotiationAllowed;
135     }
136 
137     @Override
138     public void onOpen()
139     {
140         try
141         {
142             // Begin the handshake
143             _sslEngine.beginHandshake();
144             super.onOpen();
145             getDecryptedEndPoint().getConnection().onOpen();
146         }
147         catch (SSLException x)
148         {
149             getEndPoint().close();
150             throw new RuntimeIOException(x);
151         }
152     }
153 
154     @Override
155     public void onClose()
156     {
157         _decryptedEndPoint.getConnection().onClose();
158         super.onClose();
159     }
160 
161     @Override
162     public void close()
163     {
164         getDecryptedEndPoint().getConnection().close();
165     }
166 
167     @Override
168     public void onFillable()
169     {
170         // onFillable means that there are encrypted bytes ready to be filled.
171         // however we do not fill them here on this callback, but instead wakeup
172         // the decrypted readInterest and/or writeFlusher so that they will attempt
173         // to do the fill and/or flush again and these calls will do the actually
174         // filling.
175 
176         if (DEBUG)
177             LOG.debug("onFillable enter {}", _decryptedEndPoint);
178 
179         // We have received a close handshake, close the end point to send FIN.
180         if (_decryptedEndPoint.isInputShutdown())
181             _decryptedEndPoint.close();
182 
183         // wake up whoever is doing the fill or the flush so they can
184         // do all the filling, unwrapping, wrapping and flushing
185         _decryptedEndPoint.getFillInterest().fillable();
186 
187         // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
188         synchronized(_decryptedEndPoint)
189         {
190             if (_decryptedEndPoint._flushRequiresFillToProgress)
191             {
192                 _decryptedEndPoint._flushRequiresFillToProgress = false;
193                 getExecutor().execute(_runCompletWrite);
194             }
195         }
196 
197         if (DEBUG)
198             LOG.debug("onFillable exit {}", _decryptedEndPoint);
199     }
200 
201     @Override
202     public void onFillInterestedFailed(Throwable cause)
203     {
204         // this means that the fill interest in encrypted bytes has failed.
205         // However we do not handle that here on this callback, but instead wakeup
206         // the decrypted readInterest and/or writeFlusher so that they will attempt
207         // to do the fill and/or flush again and these calls will do the actually
208         // handle the cause.
209         _decryptedEndPoint.getFillInterest().onFail(cause);
210 
211         boolean failFlusher = false;
212         synchronized(_decryptedEndPoint)
213         {
214             if (_decryptedEndPoint._flushRequiresFillToProgress)
215             {
216                 _decryptedEndPoint._flushRequiresFillToProgress = false;
217                 failFlusher = true;
218             }
219         }
220         if (failFlusher)
221             _decryptedEndPoint.getWriteFlusher().onFail(cause);
222     }
223 
224     @Override
225     public String toString()
226     {
227         ByteBuffer b = _encryptedInput;
228         int ei=b==null?-1:b.remaining();
229         b = _encryptedOutput;
230         int eo=b==null?-1:b.remaining();
231         b = _decryptedInput;
232         int di=b==null?-1:b.remaining();
233 
234         return String.format("SslConnection@%x{%s,eio=%d/%d,di=%d} -> %s",
235                 hashCode(),
236                 _sslEngine.getHandshakeStatus(),
237                 ei,eo,di,
238                 _decryptedEndPoint.getConnection());
239     }
240 
241     public class DecryptedEndPoint extends AbstractEndPoint
242     {
243         private boolean _fillRequiresFlushToProgress;
244         private boolean _flushRequiresFillToProgress;
245         private boolean _cannotAcceptMoreAppDataToFlush;
246         private boolean _handshaken;
247         private boolean _underFlown;
248 
249         private final Callback _writeCallback = new Callback()
250         {
251             @Override
252             public void succeeded()
253             {
254                 // This means that a write of encrypted data has completed.  Writes are done
255                 // only if there is a pending writeflusher or a read needed to write
256                 // data.  In either case the appropriate callback is passed on.
257                 boolean fillable = false;
258                 synchronized (DecryptedEndPoint.this)
259                 {
260                     if (DEBUG)
261                         LOG.debug("write.complete {}", SslConnection.this.getEndPoint());
262 
263                     releaseEncryptedOutputBuffer();
264 
265                     _cannotAcceptMoreAppDataToFlush = false;
266 
267                     if (_fillRequiresFlushToProgress)
268                     {
269                         _fillRequiresFlushToProgress = false;
270                         fillable = true;
271                     }
272                 }
273                 if (fillable)
274                     getFillInterest().fillable();
275                 getExecutor().execute(_runCompletWrite);
276             }
277 
278             @Override
279             public void failed(final Throwable x)
280             {
281                 // This means that a write of data has failed.  Writes are done
282                 // only if there is an active writeflusher or a read needed to write
283                 // data.  In either case the appropriate callback is passed on.
284                 boolean fail_filler = false;
285                 synchronized (DecryptedEndPoint.this)
286                 {
287                     if (DEBUG)
288                         LOG.debug("{} write.failed", SslConnection.this, x);
289                     BufferUtil.clear(_encryptedOutput);
290                     releaseEncryptedOutputBuffer();
291 
292                     _cannotAcceptMoreAppDataToFlush = false;
293 
294                     if (_fillRequiresFlushToProgress)
295                     {
296                         _fillRequiresFlushToProgress = false;
297                         fail_filler = true;
298                     }
299                 }
300 
301                 final boolean filler_failed=fail_filler;
302 
303                 failedCallback(new Callback()
304                 {
305                     @Override
306                     public void succeeded()
307                     {
308                     }
309 
310                     @Override
311                     public void failed(Throwable x)
312                     {
313                         if (filler_failed)
314                             getFillInterest().onFail(x);
315                         getWriteFlusher().onFail(x);
316                     }
317 
318                 },x);
319             }
320         };
321 
322         public DecryptedEndPoint()
323         {
324             super(null,getEndPoint().getLocalAddress(), getEndPoint().getRemoteAddress());
325             setIdleTimeout(getEndPoint().getIdleTimeout());
326         }
327 
328         @Override
329         protected FillInterest getFillInterest()
330         {
331             return super.getFillInterest();
332         }
333 
334         @Override
335         public void setIdleTimeout(long idleTimeout)
336         {
337             super.setIdleTimeout(idleTimeout);
338             getEndPoint().setIdleTimeout(idleTimeout);
339         }
340 
341         @Override
342         protected WriteFlusher getWriteFlusher()
343         {
344             return super.getWriteFlusher();
345         }
346 
347         @Override
348         protected void onIncompleteFlush()
349         {
350             // This means that the decrypted endpoint write method was called and not
351             // all data could be wrapped. So either we need to write some encrypted data,
352             // OR if we are handshaking we need to read some encrypted data OR
353             // if neither then we should just try the flush again.
354             boolean try_again = false;
355             synchronized (DecryptedEndPoint.this)
356             {
357                 if (DEBUG)
358                     LOG.debug("onIncompleteFlush {}", getEndPoint());
359                 // If we have pending output data,
360                 if (BufferUtil.hasContent(_encryptedOutput))
361                 {
362                     // write it
363                     _cannotAcceptMoreAppDataToFlush = true;
364                     getEndPoint().write(_writeCallback, _encryptedOutput);
365                 }
366                 // If we are handshaking and need to read,
367                 else if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP)
368                 {
369                     // check if we are actually read blocked in order to write
370                     _flushRequiresFillToProgress = true;
371                     SslConnection.this.fillInterested();
372                 }
373                 else
374                 {
375                     // We can get here because the WriteFlusher might not see progress
376                     // when it has just flushed the encrypted data, but not consumed anymore
377                     // of the application buffers.  This is mostly avoided by another iteration
378                     // within DecryptedEndPoint flush(), but I cannot convince myself that
379                     // this is never ever the case.
380                     try_again = true;
381                 }
382             }
383 
384 
385             if (try_again)
386             {
387                 // If the output is closed,
388                 if (isOutputShutdown())
389                 {
390                     // don't bother writing, just notify of close
391                     getWriteFlusher().onClose();
392                 }
393                 // Else,
394                 else
395                 {
396                     // try to flush what is pending
397                     // because this is a special case (see above) we could probably
398                     // avoid the dispatch, but best to be sure
399                     getExecutor().execute(_runCompletWrite);
400                 }
401             }
402         }
403 
404         @Override
405         protected boolean needsFill() throws IOException
406         {
407             // This means that the decrypted data consumer has called the fillInterested
408             // method on the DecryptedEndPoint, so we have to work out if there is
409             // decrypted data to be filled or what callbacks to setup to be told when there
410             // might be more encrypted data available to attempt another call to fill
411 
412             synchronized (DecryptedEndPoint.this)
413             {
414                 // Do we already have some app data, then app can fill now so return true
415                 if (BufferUtil.hasContent(_decryptedInput))
416                     return true;
417 
418                 // If we have no encrypted data to decrypt OR we have some, but it is not enough
419                 if (BufferUtil.isEmpty(_encryptedInput) || _underFlown)
420                 {
421                     // We are not ready to read data
422 
423                     // Are we actually write blocked?
424                     if (_fillRequiresFlushToProgress)
425                     {
426                         // we must be blocked trying to write before we can read
427 
428                         // Do we have data to write
429                         if (BufferUtil.hasContent(_encryptedOutput))
430                         {
431                             // write it
432                             _cannotAcceptMoreAppDataToFlush = true;
433                             getEndPoint().write(_writeCallback, _encryptedOutput);
434                         }
435                         else
436                         {
437                             // we have already written the net data
438                             // pretend we are readable so the wrap is done by next readable callback
439                             _fillRequiresFlushToProgress = false;
440                             return true;
441                         }
442                     }
443                     else
444                     {
445                         // Normal readable callback
446                         // Get called back on onfillable when then is more data to fill
447                         SslConnection.this.fillInterested();
448                     }
449 
450                     return false;
451                 }
452                 else
453                 {
454                     // We are ready to read data
455                     return true;
456                 }
457             }
458         }
459 
460         @Override
461         public void setConnection(Connection connection)
462         {
463             if (connection instanceof AbstractConnection)
464             {
465                 AbstractConnection a = (AbstractConnection)connection;
466                 if (a.getInputBufferSize()<_sslEngine.getSession().getApplicationBufferSize())
467                     a.setInputBufferSize(_sslEngine.getSession().getApplicationBufferSize());
468             }
469             super.setConnection(connection);
470         }
471 
472         public SslConnection getSslConnection()
473         {
474             return SslConnection.this;
475         }
476 
477         @Override
478         public synchronized int fill(ByteBuffer buffer) throws IOException
479         {
480             if (DEBUG)
481                 LOG.debug("{} fill enter", SslConnection.this);
482             try
483             {
484                 // Do we already have some decrypted data?
485                 if (BufferUtil.hasContent(_decryptedInput))
486                     return BufferUtil.append(buffer,_decryptedInput);
487 
488                 // We will need a network buffer
489                 if (_encryptedInput == null)
490                     _encryptedInput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
491                 else
492                     BufferUtil.compact(_encryptedInput);
493 
494                 // We also need an app buffer, but can use the passed buffer if it is big enough
495                 ByteBuffer app_in;
496                 if (BufferUtil.space(buffer) > _sslEngine.getSession().getApplicationBufferSize())
497                     app_in = buffer;
498                 else if (_decryptedInput == null)
499                     app_in = _decryptedInput = _bufferPool.acquire(_sslEngine.getSession().getApplicationBufferSize(), _decryptedDirectBuffers);
500                 else
501                     app_in = _decryptedInput;
502 
503                 // loop filling and unwrapping until we have something
504                 while (true)
505                 {
506                     // Let's try reading some encrypted data... even if we have some already.
507                     int net_filled = getEndPoint().fill(_encryptedInput);
508                     if (DEBUG)
509                         LOG.debug("{} filled {} encrypted bytes", SslConnection.this, net_filled);
510 
511                     decryption: while (true)
512                     {
513                         // Let's unwrap even if we have no net data because in that
514                         // case we want to fall through to the handshake handling
515                         int pos = BufferUtil.flipToFill(app_in);
516                         SSLEngineResult unwrapResult;
517                         try
518                         {
519                             unwrapResult = _sslEngine.unwrap(_encryptedInput, app_in);
520                         }
521                         finally
522                         {
523                             BufferUtil.flipToFlush(app_in, pos);
524                         }
525                         if (DEBUG)
526                             LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
527 
528                         HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
529                         HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus();
530                         Status unwrapResultStatus = unwrapResult.getStatus();
531 
532                         // Extra check on unwrapResultStatus == OK with zero length buffer is due
533                         // to SSL client on android (see bug #454773)
534                         _underFlown = unwrapResultStatus == Status.BUFFER_UNDERFLOW || unwrapResultStatus == Status.OK && unwrapResult.bytesConsumed()==0 && unwrapResult.bytesProduced()==0;
535 
536                         if (_underFlown)
537                         {
538                             if (net_filled < 0)
539                                 closeInbound();
540                             if (net_filled <= 0)
541                                 return net_filled;
542                         }
543 
544                         switch (unwrapResultStatus)
545                         {
546                             case CLOSED:
547                             {
548                                 switch (handshakeStatus)
549                                 {
550                                     case NOT_HANDSHAKING:
551                                     {
552                                         // We were not handshaking, so just tell the app we are closed
553                                         return -1;
554                                     }
555                                     case NEED_TASK:
556                                     {
557                                         _sslEngine.getDelegatedTask().run();
558                                         continue;
559                                     }
560                                     case NEED_WRAP:
561                                     {
562                                         // We need to send some handshake data (probably the close handshake).
563                                         // We return -1 so that the application can drive the close by flushing
564                                         // or shutting down the output.
565                                         return -1;
566                                     }
567                                     case NEED_UNWRAP:
568                                     {
569                                         // We expected to read more, but we got closed.
570                                         // Return -1 to indicate to the application to drive the close.
571                                         return -1;
572                                     }
573                                     default:
574                                     {
575                                         throw new IllegalStateException();
576                                     }
577                                 }
578                             }
579                             case BUFFER_UNDERFLOW:
580                             case OK:
581                             {
582                                 if (unwrapHandshakeStatus == HandshakeStatus.FINISHED && !_handshaken)
583                                 {
584                                     _handshaken = true;
585                                     if (DEBUG)
586                                         LOG.debug("{} {} handshake completed", SslConnection.this,
587                                                 _sslEngine.getUseClientMode() ? "client-side" : "resumed session server-side");
588                                 }
589 
590                                 // Check whether renegotiation is allowed
591                                 if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
592                                 {
593                                     if (DEBUG)
594                                         LOG.debug("{} renegotiation denied", SslConnection.this);
595                                     closeInbound();
596                                     return -1;
597                                 }
598 
599                                 // If bytes were produced, don't bother with the handshake status;
600                                 // pass the decrypted data to the application, which will perform
601                                 // another call to fill() or flush().
602                                 if (unwrapResult.bytesProduced() > 0)
603                                 {
604                                     if (app_in == buffer)
605                                         return unwrapResult.bytesProduced();
606                                     return BufferUtil.append(buffer,_decryptedInput);
607                                 }
608 
609                                 switch (handshakeStatus)
610                                 {
611                                     case NOT_HANDSHAKING:
612                                     {
613                                         if (_underFlown)
614                                             break decryption;
615                                         continue;
616                                     }
617                                     case NEED_TASK:
618                                     {
619                                         _sslEngine.getDelegatedTask().run();
620                                         continue;
621                                     }
622                                     case NEED_WRAP:
623                                     {
624                                         // If we are called from flush()
625                                         // return to let it do the wrapping.
626                                         if (buffer == __FLUSH_CALLED_FILL)
627                                             return 0;
628 
629                                         _fillRequiresFlushToProgress = true;
630                                         flush(__FILL_CALLED_FLUSH);
631                                         if (BufferUtil.isEmpty(_encryptedOutput))
632                                         {
633                                             // The flush wrote all the encrypted bytes so continue to fill
634                                             _fillRequiresFlushToProgress = false;
635                                             continue;
636                                         }
637                                         else
638                                         {
639                                             // The flush did not complete, return from fill()
640                                             // and let the write completion mechanism to kick in.
641                                             return 0;
642                                         }
643                                     }
644                                     case NEED_UNWRAP:
645                                     {
646                                         if (_underFlown)
647                                             break decryption;
648                                         continue;
649                                     }
650                                     default:
651                                     {
652                                         throw new IllegalStateException();
653                                     }
654                                 }
655                             }
656                             default:
657                             {
658                                 throw new IllegalStateException();
659                             }
660                         }
661                     }
662                 }
663             }
664             catch (Exception e)
665             {
666                 getEndPoint().close();
667                 throw e;
668             }
669             finally
670             {
671                 // If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
672                 if (_flushRequiresFillToProgress)
673                 {
674                     _flushRequiresFillToProgress = false;
675                     getExecutor().execute(_runCompletWrite);
676                 }
677 
678                 if (_encryptedInput != null && !_encryptedInput.hasRemaining())
679                 {
680                     _bufferPool.release(_encryptedInput);
681                     _encryptedInput = null;
682                 }
683                 if (_decryptedInput != null && !_decryptedInput.hasRemaining())
684                 {
685                     _bufferPool.release(_decryptedInput);
686                     _decryptedInput = null;
687                 }
688                 if (DEBUG)
689                     LOG.debug("{} fill exit", SslConnection.this);
690             }
691         }
692 
693         private void closeInbound()
694         {
695             try
696             {
697                 _sslEngine.closeInbound();
698             }
699             catch (SSLException x)
700             {
701                 LOG.ignore(x);
702             }
703         }
704 
705         @Override
706         public synchronized boolean flush(ByteBuffer... appOuts) throws IOException
707         {
708             // The contract for flush does not require that all appOuts bytes are written
709             // or even that any appOut bytes are written!  If the connection is write block
710             // or busy handshaking, then zero bytes may be taken from appOuts and this method
711             // will return 0 (even if some handshake bytes were flushed and filled).
712             // it is the applications responsibility to call flush again - either in a busy loop
713             // or better yet by using EndPoint#write to do the flushing.
714 
715             if (DEBUG)
716                 LOG.debug("{} flush enter {}", SslConnection.this, Arrays.toString(appOuts));
717             int consumed=0;
718             try
719             {
720                 if (_cannotAcceptMoreAppDataToFlush)
721                 {
722                     if (_sslEngine.isOutboundDone())
723                         throw new EofException(new ClosedChannelException());
724                     return false;
725                 }
726 
727                 // We will need a network buffer
728                 if (_encryptedOutput == null)
729                     _encryptedOutput = _bufferPool.acquire(_sslEngine.getSession().getPacketBufferSize(), _encryptedDirectBuffers);
730 
731                 while (true)
732                 {
733                     // We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer
734                     BufferUtil.compact(_encryptedOutput);
735                     int pos = BufferUtil.flipToFill(_encryptedOutput);
736                     SSLEngineResult wrapResult;
737                     try
738                     {
739                         wrapResult=_sslEngine.wrap(appOuts, _encryptedOutput);
740                     }
741                     finally
742                     {
743                         BufferUtil.flipToFlush(_encryptedOutput, pos);
744                     }
745                     
746                     if (DEBUG)
747                         LOG.debug("{} wrap {}", SslConnection.this, wrapResult);
748                     if (wrapResult.bytesConsumed()>0)
749                         consumed+=wrapResult.bytesConsumed();
750                     Status wrapResultStatus = wrapResult.getStatus();
751 
752                     boolean allConsumed=true;
753                     for (ByteBuffer b : appOuts)
754                         if (BufferUtil.hasContent(b))
755                             allConsumed=false;
756 
757                     // and deal with the results returned from the sslEngineWrap
758                     switch (wrapResultStatus)
759                     {
760                         case CLOSED:
761                             // The SSL engine has close, but there may be close handshake that needs to be written
762                             if (BufferUtil.hasContent(_encryptedOutput))
763                             {
764                                 _cannotAcceptMoreAppDataToFlush = true;
765                                 getEndPoint().flush(_encryptedOutput);
766                                 getEndPoint().shutdownOutput();
767                                 // If we failed to flush the close handshake then we will just pretend that
768                                 // the write has progressed normally and let a subsequent call to flush
769                                 // (or WriteFlusher#onIncompleteFlushed) to finish writing the close handshake.
770                                 // The caller will find out about the close on a subsequent flush or fill.
771                                 if (BufferUtil.hasContent(_encryptedOutput))
772                                     return false;
773                             }
774                             // otherwise we have written, and the caller will close the underlying connection
775                             else
776                             {
777                                 getEndPoint().shutdownOutput();
778                             }
779                             return allConsumed;
780 
781                         case BUFFER_UNDERFLOW:
782                             throw new IllegalStateException();
783 
784                         default:
785                             if (DEBUG)
786                                 LOG.debug("{} {} {}", this, wrapResultStatus, BufferUtil.toDetailString(_encryptedOutput));
787 
788                             if (wrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED && !_handshaken)
789                             {
790                                 _handshaken = true;
791                                 if (DEBUG)
792                                     LOG.debug("{} {} handshake completed", SslConnection.this, "server-side");
793                             }
794 
795                             HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
796 
797                             // Check whether renegotiation is allowed
798                             if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
799                             {
800                                 if (DEBUG)
801                                     LOG.debug("{} renegotiation denied", SslConnection.this);
802                                 getEndPoint().shutdownOutput();
803                                 return allConsumed;
804                             }
805 
806                             // if we have net bytes, let's try to flush them
807                             if (BufferUtil.hasContent(_encryptedOutput))
808                                 if (!getEndPoint().flush(_encryptedOutput))
809                                     getEndPoint().flush(_encryptedOutput); // one retry
810 
811                             // But we also might have more to do for the handshaking state.
812                             switch (handshakeStatus)
813                             {
814                                 case NOT_HANDSHAKING:
815                                     // If we have not consumed all and had just finished handshaking, then we may
816                                     // have just flushed the last handshake in the encrypted buffers, so we should
817                                     // try again.
818                                     if (!allConsumed && wrapResult.getHandshakeStatus()==HandshakeStatus.FINISHED && BufferUtil.isEmpty(_encryptedOutput))
819                                         continue;
820 
821                                     // Return true if we consumed all the bytes and encrypted are all flushed
822                                     return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
823 
824                                 case NEED_TASK:
825                                     // run the task and continue
826                                     _sslEngine.getDelegatedTask().run();
827                                     continue;
828 
829                                 case NEED_WRAP:
830                                     // Hey we just wrapped! Oh well who knows what the sslEngine is thinking, so continue and we will wrap again
831                                     continue;
832 
833                                 case NEED_UNWRAP:
834                                     // Ah we need to fill some data so we can write.
835                                     // So if we were not called from fill and the app is not reading anyway
836                                     if (appOuts[0]!=__FILL_CALLED_FLUSH && !getFillInterest().isInterested())
837                                     {
838                                         // Tell the onFillable method that there might be a write to complete
839                                         _flushRequiresFillToProgress = true;
840                                         fill(__FLUSH_CALLED_FILL);
841                                         // Check if after the fill() we need to wrap again
842                                         if (handshakeStatus == HandshakeStatus.NEED_WRAP)
843                                             continue;
844                                     }
845                                     return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
846 
847                                 case FINISHED:
848                                     throw new IllegalStateException();
849                             }
850                     }
851                 }
852             }
853             finally
854             {
855                 if (DEBUG)
856                     LOG.debug("{} flush exit, consumed {}", SslConnection.this, consumed);
857                 releaseEncryptedOutputBuffer();
858             }
859         }
860 
861         private void releaseEncryptedOutputBuffer()
862         {
863             if (!Thread.holdsLock(DecryptedEndPoint.this))
864                 throw new IllegalStateException();
865             if (_encryptedOutput != null && !_encryptedOutput.hasRemaining())
866             {
867                 _bufferPool.release(_encryptedOutput);
868                 _encryptedOutput = null;
869             }
870         }
871 
872         @Override
873         public void shutdownOutput()
874         {
875             boolean ishut = isInputShutdown();
876             boolean oshut = isOutputShutdown();
877             if (DEBUG)
878                 LOG.debug("{} shutdownOutput: oshut={}, ishut={}", SslConnection.this, oshut, ishut);
879             if (ishut)
880             {
881                 // Aggressively close, since inbound close alert has already been processed
882                 // and the TLS specification allows to close the connection directly, which
883                 // is what most other implementations expect: a FIN rather than a TLS close
884                 // reply. If a TLS close reply is sent, most implementations send a RST.
885                 getEndPoint().close();
886             }
887             else if (!oshut)
888             {
889                 try
890                 {
891                     _sslEngine.closeOutbound();
892                     flush(BufferUtil.EMPTY_BUFFER); // Send close handshake
893                     SslConnection.this.fillInterested(); // seek reply FIN or RST or close handshake
894                 }
895                 catch (Exception e)
896                 {
897                     LOG.ignore(e);
898                     getEndPoint().close();
899                 }
900             }
901         }
902 
903         @Override
904         public boolean isOutputShutdown()
905         {
906             return _sslEngine.isOutboundDone() || getEndPoint().isOutputShutdown();
907         }
908 
909         @Override
910         public void close()
911         {
912             super.close();
913             // First send the TLS Close Alert, then the FIN
914             shutdownOutput();
915             getEndPoint().close();
916         }
917 
918         @Override
919         public boolean isOpen()
920         {
921             return getEndPoint().isOpen();
922         }
923 
924         @Override
925         public Object getTransport()
926         {
927             return getEndPoint();
928         }
929 
930         @Override
931         public boolean isInputShutdown()
932         {
933             return _sslEngine.isInboundDone();
934         }
935 
936         @Override
937         public String toString()
938         {
939             return super.toString()+"->"+getEndPoint().toString();
940         }
941     }
942 }