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