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