PageRenderTime 31ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 1ms

/handler/src/main/java/io/netty/handler/ssl/SslHandler.java

http://github.com/netty/netty
Java | 2364 lines | 1538 code | 216 blank | 610 comment | 303 complexity | a88f759a49bc67481fa6e49390a37f4e MD5 | raw file
Possible License(s): Apache-2.0
  1. /*
  2. * Copyright 2012 The Netty Project
  3. *
  4. * The Netty Project licenses this file to you under the Apache License,
  5. * version 2.0 (the "License"); you may not use this file except in compliance
  6. * with the License. You may obtain a copy of the License at:
  7. *
  8. * https://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations
  14. * under the License.
  15. */
  16. package io.netty.handler.ssl;
  17. import io.netty.buffer.ByteBuf;
  18. import io.netty.buffer.ByteBufAllocator;
  19. import io.netty.buffer.ByteBufUtil;
  20. import io.netty.buffer.CompositeByteBuf;
  21. import io.netty.buffer.Unpooled;
  22. import io.netty.channel.AbstractCoalescingBufferQueue;
  23. import io.netty.channel.Channel;
  24. import io.netty.channel.ChannelConfig;
  25. import io.netty.channel.ChannelException;
  26. import io.netty.channel.ChannelFuture;
  27. import io.netty.channel.ChannelFutureListener;
  28. import io.netty.channel.ChannelHandlerContext;
  29. import io.netty.channel.ChannelInboundHandler;
  30. import io.netty.channel.ChannelOption;
  31. import io.netty.channel.ChannelOutboundBuffer;
  32. import io.netty.channel.ChannelOutboundHandler;
  33. import io.netty.channel.ChannelPipeline;
  34. import io.netty.channel.ChannelPromise;
  35. import io.netty.handler.codec.ByteToMessageDecoder;
  36. import io.netty.handler.codec.DecoderException;
  37. import io.netty.handler.codec.UnsupportedMessageTypeException;
  38. import io.netty.util.ReferenceCountUtil;
  39. import io.netty.util.concurrent.DefaultPromise;
  40. import io.netty.util.concurrent.EventExecutor;
  41. import io.netty.util.concurrent.Future;
  42. import io.netty.util.concurrent.FutureListener;
  43. import io.netty.util.concurrent.ImmediateExecutor;
  44. import io.netty.util.concurrent.Promise;
  45. import io.netty.util.concurrent.PromiseNotifier;
  46. import io.netty.util.internal.ObjectUtil;
  47. import io.netty.util.internal.PlatformDependent;
  48. import io.netty.util.internal.UnstableApi;
  49. import io.netty.util.internal.logging.InternalLogger;
  50. import io.netty.util.internal.logging.InternalLoggerFactory;
  51. import java.io.IOException;
  52. import java.net.SocketAddress;
  53. import java.nio.ByteBuffer;
  54. import java.nio.channels.ClosedChannelException;
  55. import java.nio.channels.DatagramChannel;
  56. import java.nio.channels.SocketChannel;
  57. import java.util.List;
  58. import java.util.concurrent.Executor;
  59. import java.util.concurrent.RejectedExecutionException;
  60. import java.util.concurrent.ScheduledFuture;
  61. import java.util.concurrent.TimeUnit;
  62. import java.util.regex.Pattern;
  63. import javax.net.ssl.SSLEngine;
  64. import javax.net.ssl.SSLEngineResult;
  65. import javax.net.ssl.SSLEngineResult.HandshakeStatus;
  66. import javax.net.ssl.SSLEngineResult.Status;
  67. import javax.net.ssl.SSLException;
  68. import javax.net.ssl.SSLHandshakeException;
  69. import javax.net.ssl.SSLSession;
  70. import static io.netty.buffer.ByteBufUtil.ensureWritableSuccess;
  71. import static io.netty.handler.ssl.SslUtils.getEncryptedPacketLength;
  72. import static io.netty.util.internal.ObjectUtil.checkNotNull;
  73. import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
  74. /**
  75. * Adds <a href="https://en.wikipedia.org/wiki/Transport_Layer_Security">SSL
  76. * &middot; TLS</a> and StartTLS support to a {@link Channel}. Please refer
  77. * to the <strong>"SecureChat"</strong> example in the distribution or the web
  78. * site for the detailed usage.
  79. *
  80. * <h3>Beginning the handshake</h3>
  81. * <p>
  82. * Beside using the handshake {@link ChannelFuture} to get notified about the completion of the handshake it's
  83. * also possible to detect it by implement the
  84. * {@link ChannelInboundHandler#userEventTriggered(ChannelHandlerContext, Object)}
  85. * method and check for a {@link SslHandshakeCompletionEvent}.
  86. *
  87. * <h3>Handshake</h3>
  88. * <p>
  89. * The handshake will be automatically issued for you once the {@link Channel} is active and
  90. * {@link SSLEngine#getUseClientMode()} returns {@code true}.
  91. * So no need to bother with it by your self.
  92. *
  93. * <h3>Closing the session</h3>
  94. * <p>
  95. * To close the SSL session, the {@link #closeOutbound()} method should be
  96. * called to send the {@code close_notify} message to the remote peer. One
  97. * exception is when you close the {@link Channel} - {@link SslHandler}
  98. * intercepts the close request and send the {@code close_notify} message
  99. * before the channel closure automatically. Once the SSL session is closed,
  100. * it is not reusable, and consequently you should create a new
  101. * {@link SslHandler} with a new {@link SSLEngine} as explained in the
  102. * following section.
  103. *
  104. * <h3>Restarting the session</h3>
  105. * <p>
  106. * To restart the SSL session, you must remove the existing closed
  107. * {@link SslHandler} from the {@link ChannelPipeline}, insert a new
  108. * {@link SslHandler} with a new {@link SSLEngine} into the pipeline,
  109. * and start the handshake process as described in the first section.
  110. *
  111. * <h3>Implementing StartTLS</h3>
  112. * <p>
  113. * <a href="https://en.wikipedia.org/wiki/STARTTLS">StartTLS</a> is the
  114. * communication pattern that secures the wire in the middle of the plaintext
  115. * connection. Please note that it is different from SSL &middot; TLS, that
  116. * secures the wire from the beginning of the connection. Typically, StartTLS
  117. * is composed of three steps:
  118. * <ol>
  119. * <li>Client sends a StartTLS request to server.</li>
  120. * <li>Server sends a StartTLS response to client.</li>
  121. * <li>Client begins SSL handshake.</li>
  122. * </ol>
  123. * If you implement a server, you need to:
  124. * <ol>
  125. * <li>create a new {@link SslHandler} instance with {@code startTls} flag set
  126. * to {@code true},</li>
  127. * <li>insert the {@link SslHandler} to the {@link ChannelPipeline}, and</li>
  128. * <li>write a StartTLS response.</li>
  129. * </ol>
  130. * Please note that you must insert {@link SslHandler} <em>before</em> sending
  131. * the StartTLS response. Otherwise the client can send begin SSL handshake
  132. * before {@link SslHandler} is inserted to the {@link ChannelPipeline}, causing
  133. * data corruption.
  134. * <p>
  135. * The client-side implementation is much simpler.
  136. * <ol>
  137. * <li>Write a StartTLS request,</li>
  138. * <li>wait for the StartTLS response,</li>
  139. * <li>create a new {@link SslHandler} instance with {@code startTls} flag set
  140. * to {@code false},</li>
  141. * <li>insert the {@link SslHandler} to the {@link ChannelPipeline}, and</li>
  142. * <li>Initiate SSL handshake.</li>
  143. * </ol>
  144. *
  145. * <h3>Known issues</h3>
  146. * <p>
  147. * Because of a known issue with the current implementation of the SslEngine that comes
  148. * with Java it may be possible that you see blocked IO-Threads while a full GC is done.
  149. * <p>
  150. * So if you are affected you can workaround this problem by adjust the cache settings
  151. * like shown below:
  152. *
  153. * <pre>
  154. * SslContext context = ...;
  155. * context.getServerSessionContext().setSessionCacheSize(someSaneSize);
  156. * context.getServerSessionContext().setSessionTime(someSameTimeout);
  157. * </pre>
  158. * <p>
  159. * What values to use here depends on the nature of your application and should be set
  160. * based on monitoring and debugging of it.
  161. * For more details see
  162. * <a href="https://github.com/netty/netty/issues/832">#832</a> in our issue tracker.
  163. */
  164. public class SslHandler extends ByteToMessageDecoder implements ChannelOutboundHandler {
  165. private static final InternalLogger logger =
  166. InternalLoggerFactory.getInstance(SslHandler.class);
  167. private static final Pattern IGNORABLE_CLASS_IN_STACK = Pattern.compile(
  168. "^.*(?:Socket|Datagram|Sctp|Udt)Channel.*$");
  169. private static final Pattern IGNORABLE_ERROR_MESSAGE = Pattern.compile(
  170. "^.*(?:connection.*(?:reset|closed|abort|broken)|broken.*pipe).*$", Pattern.CASE_INSENSITIVE);
  171. private static final int STATE_SENT_FIRST_MESSAGE = 1;
  172. private static final int STATE_FLUSHED_BEFORE_HANDSHAKE = 1 << 1;
  173. private static final int STATE_READ_DURING_HANDSHAKE = 1 << 2;
  174. private static final int STATE_HANDSHAKE_STARTED = 1 << 3;
  175. /**
  176. * Set by wrap*() methods when something is produced.
  177. * {@link #channelReadComplete(ChannelHandlerContext)} will check this flag, clear it, and call ctx.flush().
  178. */
  179. private static final int STATE_NEEDS_FLUSH = 1 << 4;
  180. private static final int STATE_OUTBOUND_CLOSED = 1 << 5;
  181. private static final int STATE_CLOSE_NOTIFY = 1 << 6;
  182. private static final int STATE_PROCESS_TASK = 1 << 7;
  183. /**
  184. * This flag is used to determine if we need to call {@link ChannelHandlerContext#read()} to consume more data
  185. * when {@link ChannelConfig#isAutoRead()} is {@code false}.
  186. */
  187. private static final int STATE_FIRE_CHANNEL_READ = 1 << 8;
  188. private static final int STATE_UNWRAP_REENTRY = 1 << 9;
  189. /**
  190. * <a href="https://tools.ietf.org/html/rfc5246#section-6.2">2^14</a> which is the maximum sized plaintext chunk
  191. * allowed by the TLS RFC.
  192. */
  193. private static final int MAX_PLAINTEXT_LENGTH = 16 * 1024;
  194. private enum SslEngineType {
  195. TCNATIVE(true, COMPOSITE_CUMULATOR) {
  196. @Override
  197. SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException {
  198. int nioBufferCount = in.nioBufferCount();
  199. int writerIndex = out.writerIndex();
  200. final SSLEngineResult result;
  201. if (nioBufferCount > 1) {
  202. /*
  203. * If {@link OpenSslEngine} is in use,
  204. * we can use a special {@link OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} method
  205. * that accepts multiple {@link ByteBuffer}s without additional memory copies.
  206. */
  207. ReferenceCountedOpenSslEngine opensslEngine = (ReferenceCountedOpenSslEngine) handler.engine;
  208. try {
  209. handler.singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes());
  210. result = opensslEngine.unwrap(in.nioBuffers(in.readerIndex(), len), handler.singleBuffer);
  211. } finally {
  212. handler.singleBuffer[0] = null;
  213. }
  214. } else {
  215. result = handler.engine.unwrap(toByteBuffer(in, in.readerIndex(), len),
  216. toByteBuffer(out, writerIndex, out.writableBytes()));
  217. }
  218. out.writerIndex(writerIndex + result.bytesProduced());
  219. return result;
  220. }
  221. @Override
  222. ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
  223. int pendingBytes, int numComponents) {
  224. return allocator.directBuffer(((ReferenceCountedOpenSslEngine) handler.engine)
  225. .calculateMaxLengthForWrap(pendingBytes, numComponents));
  226. }
  227. @Override
  228. int calculatePendingData(SslHandler handler, int guess) {
  229. int sslPending = ((ReferenceCountedOpenSslEngine) handler.engine).sslPending();
  230. return sslPending > 0 ? sslPending : guess;
  231. }
  232. @Override
  233. boolean jdkCompatibilityMode(SSLEngine engine) {
  234. return ((ReferenceCountedOpenSslEngine) engine).jdkCompatibilityMode;
  235. }
  236. },
  237. CONSCRYPT(true, COMPOSITE_CUMULATOR) {
  238. @Override
  239. SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException {
  240. int nioBufferCount = in.nioBufferCount();
  241. int writerIndex = out.writerIndex();
  242. final SSLEngineResult result;
  243. if (nioBufferCount > 1) {
  244. /*
  245. * Use a special unwrap method without additional memory copies.
  246. */
  247. try {
  248. handler.singleBuffer[0] = toByteBuffer(out, writerIndex, out.writableBytes());
  249. result = ((ConscryptAlpnSslEngine) handler.engine).unwrap(
  250. in.nioBuffers(in.readerIndex(), len),
  251. handler.singleBuffer);
  252. } finally {
  253. handler.singleBuffer[0] = null;
  254. }
  255. } else {
  256. result = handler.engine.unwrap(toByteBuffer(in, in.readerIndex(), len),
  257. toByteBuffer(out, writerIndex, out.writableBytes()));
  258. }
  259. out.writerIndex(writerIndex + result.bytesProduced());
  260. return result;
  261. }
  262. @Override
  263. ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
  264. int pendingBytes, int numComponents) {
  265. return allocator.directBuffer(
  266. ((ConscryptAlpnSslEngine) handler.engine).calculateOutNetBufSize(pendingBytes, numComponents));
  267. }
  268. @Override
  269. int calculatePendingData(SslHandler handler, int guess) {
  270. return guess;
  271. }
  272. @Override
  273. boolean jdkCompatibilityMode(SSLEngine engine) {
  274. return true;
  275. }
  276. },
  277. JDK(false, MERGE_CUMULATOR) {
  278. @Override
  279. SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException {
  280. int writerIndex = out.writerIndex();
  281. ByteBuffer inNioBuffer = toByteBuffer(in, in.readerIndex(), len);
  282. int position = inNioBuffer.position();
  283. final SSLEngineResult result = handler.engine.unwrap(inNioBuffer,
  284. toByteBuffer(out, writerIndex, out.writableBytes()));
  285. out.writerIndex(writerIndex + result.bytesProduced());
  286. // This is a workaround for a bug in Android 5.0. Android 5.0 does not correctly update the
  287. // SSLEngineResult.bytesConsumed() in some cases and just return 0.
  288. //
  289. // See:
  290. // - https://android-review.googlesource.com/c/platform/external/conscrypt/+/122080
  291. // - https://github.com/netty/netty/issues/7758
  292. if (result.bytesConsumed() == 0) {
  293. int consumed = inNioBuffer.position() - position;
  294. if (consumed != result.bytesConsumed()) {
  295. // Create a new SSLEngineResult with the correct bytesConsumed().
  296. return new SSLEngineResult(
  297. result.getStatus(), result.getHandshakeStatus(), consumed, result.bytesProduced());
  298. }
  299. }
  300. return result;
  301. }
  302. @Override
  303. ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
  304. int pendingBytes, int numComponents) {
  305. // As for the JDK SSLEngine we always need to allocate buffers of the size required by the SSLEngine
  306. // (normally ~16KB). This is required even if the amount of data to encrypt is very small. Use heap
  307. // buffers to reduce the native memory usage.
  308. //
  309. // Beside this the JDK SSLEngine also (as of today) will do an extra heap to direct buffer copy
  310. // if a direct buffer is used as its internals operate on byte[].
  311. return allocator.heapBuffer(handler.engine.getSession().getPacketBufferSize());
  312. }
  313. @Override
  314. int calculatePendingData(SslHandler handler, int guess) {
  315. return guess;
  316. }
  317. @Override
  318. boolean jdkCompatibilityMode(SSLEngine engine) {
  319. return true;
  320. }
  321. };
  322. static SslEngineType forEngine(SSLEngine engine) {
  323. return engine instanceof ReferenceCountedOpenSslEngine ? TCNATIVE :
  324. engine instanceof ConscryptAlpnSslEngine ? CONSCRYPT : JDK;
  325. }
  326. SslEngineType(boolean wantsDirectBuffer, Cumulator cumulator) {
  327. this.wantsDirectBuffer = wantsDirectBuffer;
  328. this.cumulator = cumulator;
  329. }
  330. abstract SSLEngineResult unwrap(SslHandler handler, ByteBuf in, int len, ByteBuf out) throws SSLException;
  331. abstract int calculatePendingData(SslHandler handler, int guess);
  332. abstract boolean jdkCompatibilityMode(SSLEngine engine);
  333. abstract ByteBuf allocateWrapBuffer(SslHandler handler, ByteBufAllocator allocator,
  334. int pendingBytes, int numComponents);
  335. // BEGIN Platform-dependent flags
  336. /**
  337. * {@code true} if and only if {@link SSLEngine} expects a direct buffer and so if a heap buffer
  338. * is given will make an extra memory copy.
  339. */
  340. final boolean wantsDirectBuffer;
  341. // END Platform-dependent flags
  342. /**
  343. * When using JDK {@link SSLEngine}, we use {@link #MERGE_CUMULATOR} because it works only with
  344. * one {@link ByteBuffer}.
  345. *
  346. * When using {@link OpenSslEngine}, we can use {@link #COMPOSITE_CUMULATOR} because it has
  347. * {@link OpenSslEngine#unwrap(ByteBuffer[], ByteBuffer[])} which works with multiple {@link ByteBuffer}s
  348. * and which does not need to do extra memory copies.
  349. */
  350. final Cumulator cumulator;
  351. }
  352. private volatile ChannelHandlerContext ctx;
  353. private final SSLEngine engine;
  354. private final SslEngineType engineType;
  355. private final Executor delegatedTaskExecutor;
  356. private final boolean jdkCompatibilityMode;
  357. /**
  358. * Used if {@link SSLEngine#wrap(ByteBuffer[], ByteBuffer)} and {@link SSLEngine#unwrap(ByteBuffer, ByteBuffer[])}
  359. * should be called with a {@link ByteBuf} that is only backed by one {@link ByteBuffer} to reduce the object
  360. * creation.
  361. */
  362. private final ByteBuffer[] singleBuffer = new ByteBuffer[1];
  363. private final boolean startTls;
  364. private final SslTasksRunner sslTaskRunnerForUnwrap = new SslTasksRunner(true);
  365. private final SslTasksRunner sslTaskRunner = new SslTasksRunner(false);
  366. private SslHandlerCoalescingBufferQueue pendingUnencryptedWrites;
  367. private Promise<Channel> handshakePromise = new LazyChannelPromise();
  368. private final LazyChannelPromise sslClosePromise = new LazyChannelPromise();
  369. private int packetLength;
  370. private short state;
  371. private volatile long handshakeTimeoutMillis = 10000;
  372. private volatile long closeNotifyFlushTimeoutMillis = 3000;
  373. private volatile long closeNotifyReadTimeoutMillis;
  374. volatile int wrapDataSize = MAX_PLAINTEXT_LENGTH;
  375. /**
  376. * Creates a new instance which runs all delegated tasks directly on the {@link EventExecutor}.
  377. *
  378. * @param engine the {@link SSLEngine} this handler will use
  379. */
  380. public SslHandler(SSLEngine engine) {
  381. this(engine, false);
  382. }
  383. /**
  384. * Creates a new instance which runs all delegated tasks directly on the {@link EventExecutor}.
  385. *
  386. * @param engine the {@link SSLEngine} this handler will use
  387. * @param startTls {@code true} if the first write request shouldn't be
  388. * encrypted by the {@link SSLEngine}
  389. */
  390. public SslHandler(SSLEngine engine, boolean startTls) {
  391. this(engine, startTls, ImmediateExecutor.INSTANCE);
  392. }
  393. /**
  394. * Creates a new instance.
  395. *
  396. * @param engine the {@link SSLEngine} this handler will use
  397. * @param delegatedTaskExecutor the {@link Executor} that will be used to execute tasks that are returned by
  398. * {@link SSLEngine#getDelegatedTask()}.
  399. */
  400. public SslHandler(SSLEngine engine, Executor delegatedTaskExecutor) {
  401. this(engine, false, delegatedTaskExecutor);
  402. }
  403. /**
  404. * Creates a new instance.
  405. *
  406. * @param engine the {@link SSLEngine} this handler will use
  407. * @param startTls {@code true} if the first write request shouldn't be
  408. * encrypted by the {@link SSLEngine}
  409. * @param delegatedTaskExecutor the {@link Executor} that will be used to execute tasks that are returned by
  410. * {@link SSLEngine#getDelegatedTask()}.
  411. */
  412. public SslHandler(SSLEngine engine, boolean startTls, Executor delegatedTaskExecutor) {
  413. this.engine = ObjectUtil.checkNotNull(engine, "engine");
  414. this.delegatedTaskExecutor = ObjectUtil.checkNotNull(delegatedTaskExecutor, "delegatedTaskExecutor");
  415. engineType = SslEngineType.forEngine(engine);
  416. this.startTls = startTls;
  417. this.jdkCompatibilityMode = engineType.jdkCompatibilityMode(engine);
  418. setCumulator(engineType.cumulator);
  419. }
  420. public long getHandshakeTimeoutMillis() {
  421. return handshakeTimeoutMillis;
  422. }
  423. public void setHandshakeTimeout(long handshakeTimeout, TimeUnit unit) {
  424. checkNotNull(unit, "unit");
  425. setHandshakeTimeoutMillis(unit.toMillis(handshakeTimeout));
  426. }
  427. public void setHandshakeTimeoutMillis(long handshakeTimeoutMillis) {
  428. this.handshakeTimeoutMillis = checkPositiveOrZero(handshakeTimeoutMillis, "handshakeTimeoutMillis");
  429. }
  430. /**
  431. * Sets the number of bytes to pass to each {@link SSLEngine#wrap(ByteBuffer[], int, int, ByteBuffer)} call.
  432. * <p>
  433. * This value will partition data which is passed to write
  434. * {@link #write(ChannelHandlerContext, Object, ChannelPromise)}. The partitioning will work as follows:
  435. * <ul>
  436. * <li>If {@code wrapDataSize <= 0} then we will write each data chunk as is.</li>
  437. * <li>If {@code wrapDataSize > data size} then we will attempt to aggregate multiple data chunks together.</li>
  438. * <li>If {@code wrapDataSize > data size} Else if {@code wrapDataSize <= data size} then we will divide the data
  439. * into chunks of {@code wrapDataSize} when writing.</li>
  440. * </ul>
  441. * <p>
  442. * If the {@link SSLEngine} doesn't support a gather wrap operation (e.g. {@link SslProvider#OPENSSL}) then
  443. * aggregating data before wrapping can help reduce the ratio between TLS overhead vs data payload which will lead
  444. * to better goodput. Writing fixed chunks of data can also help target the underlying transport's (e.g. TCP)
  445. * frame size. Under lossy/congested network conditions this may help the peer get full TLS packets earlier and
  446. * be able to do work sooner, as opposed to waiting for the all the pieces of the TLS packet to arrive.
  447. * @param wrapDataSize the number of bytes which will be passed to each
  448. * {@link SSLEngine#wrap(ByteBuffer[], int, int, ByteBuffer)} call.
  449. */
  450. @UnstableApi
  451. public final void setWrapDataSize(int wrapDataSize) {
  452. this.wrapDataSize = wrapDataSize;
  453. }
  454. /**
  455. * @deprecated use {@link #getCloseNotifyFlushTimeoutMillis()}
  456. */
  457. @Deprecated
  458. public long getCloseNotifyTimeoutMillis() {
  459. return getCloseNotifyFlushTimeoutMillis();
  460. }
  461. /**
  462. * @deprecated use {@link #setCloseNotifyFlushTimeout(long, TimeUnit)}
  463. */
  464. @Deprecated
  465. public void setCloseNotifyTimeout(long closeNotifyTimeout, TimeUnit unit) {
  466. setCloseNotifyFlushTimeout(closeNotifyTimeout, unit);
  467. }
  468. /**
  469. * @deprecated use {@link #setCloseNotifyFlushTimeoutMillis(long)}
  470. */
  471. @Deprecated
  472. public void setCloseNotifyTimeoutMillis(long closeNotifyFlushTimeoutMillis) {
  473. setCloseNotifyFlushTimeoutMillis(closeNotifyFlushTimeoutMillis);
  474. }
  475. /**
  476. * Gets the timeout for flushing the close_notify that was triggered by closing the
  477. * {@link Channel}. If the close_notify was not flushed in the given timeout the {@link Channel} will be closed
  478. * forcibly.
  479. */
  480. public final long getCloseNotifyFlushTimeoutMillis() {
  481. return closeNotifyFlushTimeoutMillis;
  482. }
  483. /**
  484. * Sets the timeout for flushing the close_notify that was triggered by closing the
  485. * {@link Channel}. If the close_notify was not flushed in the given timeout the {@link Channel} will be closed
  486. * forcibly.
  487. */
  488. public final void setCloseNotifyFlushTimeout(long closeNotifyFlushTimeout, TimeUnit unit) {
  489. setCloseNotifyFlushTimeoutMillis(unit.toMillis(closeNotifyFlushTimeout));
  490. }
  491. /**
  492. * See {@link #setCloseNotifyFlushTimeout(long, TimeUnit)}.
  493. */
  494. public final void setCloseNotifyFlushTimeoutMillis(long closeNotifyFlushTimeoutMillis) {
  495. this.closeNotifyFlushTimeoutMillis = checkPositiveOrZero(closeNotifyFlushTimeoutMillis,
  496. "closeNotifyFlushTimeoutMillis");
  497. }
  498. /**
  499. * Gets the timeout (in ms) for receiving the response for the close_notify that was triggered by closing the
  500. * {@link Channel}. This timeout starts after the close_notify message was successfully written to the
  501. * remote peer. Use {@code 0} to directly close the {@link Channel} and not wait for the response.
  502. */
  503. public final long getCloseNotifyReadTimeoutMillis() {
  504. return closeNotifyReadTimeoutMillis;
  505. }
  506. /**
  507. * Sets the timeout for receiving the response for the close_notify that was triggered by closing the
  508. * {@link Channel}. This timeout starts after the close_notify message was successfully written to the
  509. * remote peer. Use {@code 0} to directly close the {@link Channel} and not wait for the response.
  510. */
  511. public final void setCloseNotifyReadTimeout(long closeNotifyReadTimeout, TimeUnit unit) {
  512. setCloseNotifyReadTimeoutMillis(unit.toMillis(closeNotifyReadTimeout));
  513. }
  514. /**
  515. * See {@link #setCloseNotifyReadTimeout(long, TimeUnit)}.
  516. */
  517. public final void setCloseNotifyReadTimeoutMillis(long closeNotifyReadTimeoutMillis) {
  518. this.closeNotifyReadTimeoutMillis = checkPositiveOrZero(closeNotifyReadTimeoutMillis,
  519. "closeNotifyReadTimeoutMillis");
  520. }
  521. /**
  522. * Returns the {@link SSLEngine} which is used by this handler.
  523. */
  524. public SSLEngine engine() {
  525. return engine;
  526. }
  527. /**
  528. * Returns the name of the current application-level protocol.
  529. *
  530. * @return the protocol name or {@code null} if application-level protocol has not been negotiated
  531. */
  532. public String applicationProtocol() {
  533. SSLEngine engine = engine();
  534. if (!(engine instanceof ApplicationProtocolAccessor)) {
  535. return null;
  536. }
  537. return ((ApplicationProtocolAccessor) engine).getNegotiatedApplicationProtocol();
  538. }
  539. /**
  540. * Returns a {@link Future} that will get notified once the current TLS handshake completes.
  541. *
  542. * @return the {@link Future} for the initial TLS handshake if {@link #renegotiate()} was not invoked.
  543. * The {@link Future} for the most recent {@linkplain #renegotiate() TLS renegotiation} otherwise.
  544. */
  545. public Future<Channel> handshakeFuture() {
  546. return handshakePromise;
  547. }
  548. /**
  549. * Use {@link #closeOutbound()}
  550. */
  551. @Deprecated
  552. public ChannelFuture close() {
  553. return closeOutbound();
  554. }
  555. /**
  556. * Use {@link #closeOutbound(ChannelPromise)}
  557. */
  558. @Deprecated
  559. public ChannelFuture close(ChannelPromise promise) {
  560. return closeOutbound(promise);
  561. }
  562. /**
  563. * Sends an SSL {@code close_notify} message to the specified channel and
  564. * destroys the underlying {@link SSLEngine}. This will <strong>not</strong> close the underlying
  565. * {@link Channel}. If you want to also close the {@link Channel} use {@link Channel#close()} or
  566. * {@link ChannelHandlerContext#close()}
  567. */
  568. public ChannelFuture closeOutbound() {
  569. return closeOutbound(ctx.newPromise());
  570. }
  571. /**
  572. * Sends an SSL {@code close_notify} message to the specified channel and
  573. * destroys the underlying {@link SSLEngine}. This will <strong>not</strong> close the underlying
  574. * {@link Channel}. If you want to also close the {@link Channel} use {@link Channel#close()} or
  575. * {@link ChannelHandlerContext#close()}
  576. */
  577. public ChannelFuture closeOutbound(final ChannelPromise promise) {
  578. final ChannelHandlerContext ctx = this.ctx;
  579. if (ctx.executor().inEventLoop()) {
  580. closeOutbound0(promise);
  581. } else {
  582. ctx.executor().execute(new Runnable() {
  583. @Override
  584. public void run() {
  585. closeOutbound0(promise);
  586. }
  587. });
  588. }
  589. return promise;
  590. }
  591. private void closeOutbound0(ChannelPromise promise) {
  592. setState(STATE_OUTBOUND_CLOSED);
  593. engine.closeOutbound();
  594. try {
  595. flush(ctx, promise);
  596. } catch (Exception e) {
  597. if (!promise.tryFailure(e)) {
  598. logger.warn("{} flush() raised a masked exception.", ctx.channel(), e);
  599. }
  600. }
  601. }
  602. /**
  603. * Return the {@link Future} that will get notified if the inbound of the {@link SSLEngine} is closed.
  604. *
  605. * This method will return the same {@link Future} all the time.
  606. *
  607. * @see SSLEngine
  608. */
  609. public Future<Channel> sslCloseFuture() {
  610. return sslClosePromise;
  611. }
  612. @Override
  613. public void handlerRemoved0(ChannelHandlerContext ctx) throws Exception {
  614. try {
  615. if (!pendingUnencryptedWrites.isEmpty()) {
  616. // Check if queue is not empty first because create a new ChannelException is expensive
  617. pendingUnencryptedWrites.releaseAndFailAll(ctx,
  618. new ChannelException("Pending write on removal of SslHandler"));
  619. }
  620. pendingUnencryptedWrites = null;
  621. SSLHandshakeException cause = null;
  622. // If the handshake is not done yet we should fail the handshake promise and notify the rest of the
  623. // pipeline.
  624. if (!handshakePromise.isDone()) {
  625. cause = new SSLHandshakeException("SslHandler removed before handshake completed");
  626. if (handshakePromise.tryFailure(cause)) {
  627. ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
  628. }
  629. }
  630. if (!sslClosePromise.isDone()) {
  631. if (cause == null) {
  632. cause = new SSLHandshakeException("SslHandler removed before handshake completed");
  633. }
  634. notifyClosePromise(cause);
  635. }
  636. } finally {
  637. ReferenceCountUtil.release(engine);
  638. }
  639. }
  640. @Override
  641. public void bind(ChannelHandlerContext ctx, SocketAddress localAddress, ChannelPromise promise) throws Exception {
  642. ctx.bind(localAddress, promise);
  643. }
  644. @Override
  645. public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress,
  646. ChannelPromise promise) throws Exception {
  647. ctx.connect(remoteAddress, localAddress, promise);
  648. }
  649. @Override
  650. public void deregister(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
  651. ctx.deregister(promise);
  652. }
  653. @Override
  654. public void disconnect(final ChannelHandlerContext ctx,
  655. final ChannelPromise promise) throws Exception {
  656. closeOutboundAndChannel(ctx, promise, true);
  657. }
  658. @Override
  659. public void close(final ChannelHandlerContext ctx,
  660. final ChannelPromise promise) throws Exception {
  661. closeOutboundAndChannel(ctx, promise, false);
  662. }
  663. @Override
  664. public void read(ChannelHandlerContext ctx) throws Exception {
  665. if (!handshakePromise.isDone()) {
  666. setState(STATE_READ_DURING_HANDSHAKE);
  667. }
  668. ctx.read();
  669. }
  670. private static IllegalStateException newPendingWritesNullException() {
  671. return new IllegalStateException("pendingUnencryptedWrites is null, handlerRemoved0 called?");
  672. }
  673. @Override
  674. public void write(final ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
  675. if (!(msg instanceof ByteBuf)) {
  676. UnsupportedMessageTypeException exception = new UnsupportedMessageTypeException(msg, ByteBuf.class);
  677. ReferenceCountUtil.safeRelease(msg);
  678. promise.setFailure(exception);
  679. } else if (pendingUnencryptedWrites == null) {
  680. ReferenceCountUtil.safeRelease(msg);
  681. promise.setFailure(newPendingWritesNullException());
  682. } else {
  683. pendingUnencryptedWrites.add((ByteBuf) msg, promise);
  684. }
  685. }
  686. @Override
  687. public void flush(ChannelHandlerContext ctx) throws Exception {
  688. // Do not encrypt the first write request if this handler is
  689. // created with startTLS flag turned on.
  690. if (startTls && !isStateSet(STATE_SENT_FIRST_MESSAGE)) {
  691. setState(STATE_SENT_FIRST_MESSAGE);
  692. pendingUnencryptedWrites.writeAndRemoveAll(ctx);
  693. forceFlush(ctx);
  694. // Explicit start handshake processing once we send the first message. This will also ensure
  695. // we will schedule the timeout if needed.
  696. startHandshakeProcessing(true);
  697. return;
  698. }
  699. if (isStateSet(STATE_PROCESS_TASK)) {
  700. return;
  701. }
  702. try {
  703. wrapAndFlush(ctx);
  704. } catch (Throwable cause) {
  705. setHandshakeFailure(ctx, cause);
  706. PlatformDependent.throwException(cause);
  707. }
  708. }
  709. private void wrapAndFlush(ChannelHandlerContext ctx) throws SSLException {
  710. if (pendingUnencryptedWrites.isEmpty()) {
  711. // It's important to NOT use a voidPromise here as the user
  712. // may want to add a ChannelFutureListener to the ChannelPromise later.
  713. //
  714. // See https://github.com/netty/netty/issues/3364
  715. pendingUnencryptedWrites.add(Unpooled.EMPTY_BUFFER, ctx.newPromise());
  716. }
  717. if (!handshakePromise.isDone()) {
  718. setState(STATE_FLUSHED_BEFORE_HANDSHAKE);
  719. }
  720. try {
  721. wrap(ctx, false);
  722. } finally {
  723. // We may have written some parts of data before an exception was thrown so ensure we always flush.
  724. // See https://github.com/netty/netty/issues/3900#issuecomment-172481830
  725. forceFlush(ctx);
  726. }
  727. }
  728. // This method will not call setHandshakeFailure(...) !
  729. private void wrap(ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
  730. ByteBuf out = null;
  731. ByteBufAllocator alloc = ctx.alloc();
  732. try {
  733. final int wrapDataSize = this.wrapDataSize;
  734. // Only continue to loop if the handler was not removed in the meantime.
  735. // See https://github.com/netty/netty/issues/5860
  736. outer: while (!ctx.isRemoved()) {
  737. ChannelPromise promise = ctx.newPromise();
  738. ByteBuf buf = wrapDataSize > 0 ?
  739. pendingUnencryptedWrites.remove(alloc, wrapDataSize, promise) :
  740. pendingUnencryptedWrites.removeFirst(promise);
  741. if (buf == null) {
  742. break;
  743. }
  744. if (out == null) {
  745. out = allocateOutNetBuf(ctx, buf.readableBytes(), buf.nioBufferCount());
  746. }
  747. SSLEngineResult result = wrap(alloc, engine, buf, out);
  748. if (buf.isReadable()) {
  749. pendingUnencryptedWrites.addFirst(buf, promise);
  750. // When we add the buffer/promise pair back we need to be sure we don't complete the promise
  751. // later. We only complete the promise if the buffer is completely consumed.
  752. promise = null;
  753. } else {
  754. buf.release();
  755. }
  756. // We need to write any data before we invoke any methods which may trigger re-entry, otherwise
  757. // writes may occur out of order and TLS sequencing may be off (e.g. SSLV3_ALERT_BAD_RECORD_MAC).
  758. if (out.isReadable()) {
  759. final ByteBuf b = out;
  760. out = null;
  761. if (promise != null) {
  762. ctx.write(b, promise);
  763. } else {
  764. ctx.write(b);
  765. }
  766. } else if (promise != null) {
  767. ctx.write(Unpooled.EMPTY_BUFFER, promise);
  768. }
  769. // else out is not readable we can re-use it and so save an extra allocation
  770. if (result.getStatus() == Status.CLOSED) {
  771. // Make a best effort to preserve any exception that way previously encountered from the handshake
  772. // or the transport, else fallback to a general error.
  773. Throwable exception = handshakePromise.cause();
  774. if (exception == null) {
  775. exception = sslClosePromise.cause();
  776. if (exception == null) {
  777. exception = new SslClosedEngineException("SSLEngine closed already");
  778. }
  779. }
  780. pendingUnencryptedWrites.releaseAndFailAll(ctx, exception);
  781. return;
  782. } else {
  783. switch (result.getHandshakeStatus()) {
  784. case NEED_TASK:
  785. if (!runDelegatedTasks(inUnwrap)) {
  786. // We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
  787. // resume once the task completes.
  788. break outer;
  789. }
  790. break;
  791. case FINISHED:
  792. case NOT_HANDSHAKING: // work around for android bug that skips the FINISHED state.
  793. setHandshakeSuccess();
  794. break;
  795. case NEED_WRAP:
  796. // If we are expected to wrap again and we produced some data we need to ensure there
  797. // is something in the queue to process as otherwise we will not try again before there
  798. // was more added. Failing to do so may fail to produce an alert that can be
  799. // consumed by the remote peer.
  800. if (result.bytesProduced() > 0 && pendingUnencryptedWrites.isEmpty()) {
  801. pendingUnencryptedWrites.add(Unpooled.EMPTY_BUFFER);
  802. }
  803. break;
  804. case NEED_UNWRAP:
  805. // The underlying engine is starving so we need to feed it with more data.
  806. // See https://github.com/netty/netty/pull/5039
  807. readIfNeeded(ctx);
  808. return;
  809. default:
  810. throw new IllegalStateException(
  811. "Unknown handshake status: " + result.getHandshakeStatus());
  812. }
  813. }
  814. }
  815. } finally {
  816. if (out != null) {
  817. out.release();
  818. }
  819. if (inUnwrap) {
  820. setState(STATE_NEEDS_FLUSH);
  821. }
  822. }
  823. }
  824. /**
  825. * This method will not call
  826. * {@link #setHandshakeFailure(ChannelHandlerContext, Throwable, boolean, boolean, boolean)} or
  827. * {@link #setHandshakeFailure(ChannelHandlerContext, Throwable)}.
  828. * @return {@code true} if this method ends on {@link SSLEngineResult.HandshakeStatus#NOT_HANDSHAKING}.
  829. */
  830. private boolean wrapNonAppData(final ChannelHandlerContext ctx, boolean inUnwrap) throws SSLException {
  831. ByteBuf out = null;
  832. ByteBufAllocator alloc = ctx.alloc();
  833. try {
  834. // Only continue to loop if the handler was not removed in the meantime.
  835. // See https://github.com/netty/netty/issues/5860
  836. outer: while (!ctx.isRemoved()) {
  837. if (out == null) {
  838. // As this is called for the handshake we have no real idea how big the buffer needs to be.
  839. // That said 2048 should give us enough room to include everything like ALPN / NPN data.
  840. // If this is not enough we will increase the buffer in wrap(...).
  841. out = allocateOutNetBuf(ctx, 2048, 1);
  842. }
  843. SSLEngineResult result = wrap(alloc, engine, Unpooled.EMPTY_BUFFER, out);
  844. if (result.bytesProduced() > 0) {
  845. ctx.write(out).addListener(new ChannelFutureListener() {
  846. @Override
  847. public void operationComplete(ChannelFuture future) {
  848. Throwable cause = future.cause();
  849. if (cause != null) {
  850. setHandshakeFailureTransportFailure(ctx, cause);
  851. }
  852. }
  853. });
  854. if (inUnwrap) {
  855. setState(STATE_NEEDS_FLUSH);
  856. }
  857. out = null;
  858. }
  859. HandshakeStatus status = result.getHandshakeStatus();
  860. switch (status) {
  861. case FINISHED:
  862. // We may be here because we read data and discovered the remote peer initiated a renegotiation
  863. // and this write is to complete the new handshake. The user may have previously done a
  864. // writeAndFlush which wasn't able to wrap data due to needing the pending handshake, so we
  865. // attempt to wrap application data here if any is pending.
  866. if (setHandshakeSuccess() && inUnwrap && !pendingUnencryptedWrites.isEmpty()) {
  867. wrap(ctx, true);
  868. }
  869. return false;
  870. case NEED_TASK:
  871. if (!runDelegatedTasks(inUnwrap)) {
  872. // We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
  873. // resume once the task completes.
  874. break outer;
  875. }
  876. break;
  877. case NEED_UNWRAP:
  878. if (inUnwrap || unwrapNonAppData(ctx) <= 0) {
  879. // If we asked for a wrap, the engine requested an unwrap, and we are in unwrap there is
  880. // no use in trying to call wrap again because we have already attempted (or will after we
  881. // return) to feed more data to the engine.
  882. return false;
  883. }
  884. break;
  885. case NEED_WRAP:
  886. break;
  887. case NOT_HANDSHAKING:
  888. if (setHandshakeSuccess() && inUnwrap && !pendingUnencryptedWrites.isEmpty()) {
  889. wrap(ctx, true);
  890. }
  891. // Workaround for TLS False Start problem reported at:
  892. // https://github.com/netty/netty/issues/1108#issuecomment-14266970
  893. if (!inUnwrap) {
  894. unwrapNonAppData(ctx);
  895. }
  896. return true;
  897. default:
  898. throw new IllegalStateException("Unknown handshake status: " + result.getHandshakeStatus());
  899. }
  900. // Check if did not produce any bytes and if so break out of the loop, but only if we did not process
  901. // a task as last action. It's fine to not produce any data as part of executing a task.
  902. if (result.bytesProduced() == 0 && status != HandshakeStatus.NEED_TASK) {
  903. break;
  904. }
  905. // It should not consume empty buffers when it is not handshaking
  906. // Fix for Android, where it was encrypting empty buffers even when not handshaking
  907. if (result.bytesConsumed() == 0 && result.getHandshakeStatus() == HandshakeStatus.NOT_HANDSHAKING) {
  908. break;
  909. }
  910. }
  911. } finally {
  912. if (out != null) {
  913. out.release();
  914. }
  915. }
  916. return false;
  917. }
  918. private SSLEngineResult wrap(ByteBufAllocator alloc, SSLEngine engine, ByteBuf in, ByteBuf out)
  919. throws SSLException {
  920. ByteBuf newDirectIn = null;
  921. try {
  922. int readerIndex = in.readerIndex();
  923. int readableBytes = in.readableBytes();
  924. // We will call SslEngine.wrap(ByteBuffer[], ByteBuffer) to allow efficient handling of
  925. // CompositeByteBuf without force an extra memory copy when CompositeByteBuffer.nioBuffer() is called.
  926. final ByteBuffer[] in0;
  927. if (in.isDirect() || !engineType.wantsDirectBuffer) {
  928. // As CompositeByteBuf.nioBufferCount() can be expensive (as it needs to check all composed ByteBuf
  929. // to calculate the count) we will just assume a CompositeByteBuf contains more then 1 ByteBuf.
  930. // The worst that can happen is that we allocate an extra ByteBuffer[] in CompositeByteBuf.nioBuffers()
  931. // which is better then walking the composed ByteBuf in most cases.
  932. if (!(in instanceof CompositeByteBuf) && in.nioBufferCount() == 1) {
  933. in0 = singleBuffer;
  934. // We know its only backed by 1 ByteBuffer so use internalNioBuffer to keep object allocation
  935. // to a minimum.
  936. in0[0] = in.internalNioBuffer(readerIndex, readableBytes);
  937. } else {
  938. in0 = in.nioBuffers();
  939. }
  940. } else {
  941. // We could even go further here and check if its a CompositeByteBuf and if so try to decompose it and
  942. // only replace the ByteBuffer that are not direct. At the moment we just will replace the whole
  943. // CompositeByteBuf to keep the complexity to a minimum
  944. newDirectIn = alloc.directBuffer(readableBytes);
  945. newDirectIn.writeBytes(in, readerIndex, readableBytes);
  946. in0 = singleBuffer;
  947. in0[0] = newDirectIn.internalNioBuffer(newDirectIn.readerIndex(), readableBytes);
  948. }
  949. for (;;) {
  950. ByteBuffer out0 = out.nioBuffer(out.writerIndex(), out.writableBytes());
  951. SSLEngineResult result = engine.wrap(in0, out0);
  952. in.skipBytes(result.bytesConsumed());
  953. out.writerIndex(out.writerIndex() + result.bytesProduced());
  954. if (result.getStatus() == Status.BUFFER_OVERFLOW) {
  955. out.ensureWritable(engine.getSession().getPacketBufferSize());
  956. } else {
  957. return result;
  958. }
  959. }
  960. } finally {
  961. // Null out to allow GC of ByteBuffer
  962. singleBuffer[0] = null;
  963. if (newDirectIn != null) {
  964. newDirectIn.release();
  965. }
  966. }
  967. }
  968. @Override
  969. public void channelInactive(ChannelHandlerContext ctx) throws Exception {
  970. boolean handshakeFailed = handshakePromise.cause() != null;
  971. ClosedChannelException exception = new ClosedChannelException();
  972. // Make sure to release SSLEngine,
  973. // and notify the handshake future if the connection has been closed during handshake.
  974. setHandshakeFailure(ctx, exception, !isStateSet(STATE_OUTBOUND_CLOSED), isStateSet(STATE_HANDSHAKE_STARTED),
  975. false);
  976. // Ensure we always notify the sslClosePromise as well
  977. notifyClosePromise(exception);
  978. try {
  979. super.channelInactive(ctx);
  980. } catch (DecoderException e) {
  981. if (!handshakeFailed || !(e.getCause() instanceof SSLException)) {
  982. // We only rethrow the exception if the handshake did not fail before channelInactive(...) was called
  983. // as otherwise this may produce duplicated failures as super.channelInactive(...) will also call
  984. // channelRead(...).
  985. //
  986. // See https://github.com/netty/netty/issues/10119
  987. throw e;
  988. }
  989. }
  990. }
  991. @Override
  992. public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
  993. if (ignoreException(cause)) {
  994. // It is safe to ignore the 'connection reset by peer' or
  995. // 'broken pipe' error after sending close_notify.
  996. if (logger.isDebugEnabled()) {
  997. logger.debug(
  998. "{} Swallowing a harmless 'connection reset by peer / broken pipe' error that occurred " +
  999. "while writing close_notify in response to the peer's close_notify", ctx.channel(), cause);
  1000. }
  1001. // Close the connection explicitly just in case the transport
  1002. // did not close the connection automatically.
  1003. if (ctx.channel().isActive()) {
  1004. ctx.close();
  1005. }
  1006. } else {
  1007. ctx.fireExceptionCaught(cause);
  1008. }
  1009. }
  1010. /**
  1011. * Checks if the given {@link Throwable} can be ignore and just "swallowed"
  1012. *
  1013. * When an ssl connection is closed a close_notify message is sent.
  1014. * After that the peer also sends close_notify however, it's not mandatory to receive
  1015. * the close_notify. The party who sent the initial close_notify can close the connection immediately
  1016. * then the peer will get connection reset error.
  1017. *
  1018. */
  1019. private boolean ignoreException(Throwable t) {
  1020. if (!(t instanceof SSLException) && t instanceof IOException && sslClosePromise.isDone()) {
  1021. String message = t.getMessage();
  1022. // first try to match connection reset / broke peer based on the regex. This is the fastest way
  1023. // but may fail on different jdk impls or OS's
  1024. if (message != null && IGNORABLE_ERROR_MESSAGE.matcher(message).matches()) {
  1025. return true;
  1026. }
  1027. // Inspect the StackTraceElements to see if it was a connection reset / broken pipe or not
  1028. StackTraceElement[] elements = t.getStackTrace();
  1029. for (StackTraceElement element: elements) {
  1030. String classname = element.getClassName();
  1031. String methodname = element.getMethodName();
  1032. // skip all classes that belong to the io.netty package
  1033. if (classname.startsWith("io.netty.")) {
  1034. continue;
  1035. }
  1036. // check if the method name is read if not skip it
  1037. if (!"read".equals(methodname)) {
  1038. continue;
  1039. }
  1040. // This will also match against SocketInputStream which is used by openjdk 7 and maybe
  1041. // also others
  1042. if (IGNORABLE_CLASS_IN_STACK.matcher(classname).matches()) {
  1043. return true;
  1044. }
  1045. try {
  1046. // No match by now.. Try to load the class via classloader and inspect it.
  1047. // This is mainly done as other JDK implementations may differ in name of
  1048. // the impl.
  1049. Class<?> clazz = PlatformDependent.getClassLoader(getClass()).loadClass(classname);
  1050. if (SocketChannel.class.isAssignableFrom(clazz)
  1051. || DatagramChannel.class.isAssignableFrom(clazz)) {
  1052. return true;
  1053. }
  1054. // also match against SctpChannel via String matching as it may not present.
  1055. if (PlatformDependent.javaVersion() >= 7
  1056. && "com.sun.nio.sctp.SctpChannel".equals(clazz.getSuperclass().getName())) {
  1057. return true;
  1058. }
  1059. } catch (Throwable cause) {
  1060. if (logger.isDebugEnabled()) {
  1061. logger.debug("Unexpected exception while loading class {} classname {}",
  1062. getClass(), classname, cause);
  1063. }
  1064. }
  1065. }
  1066. }
  1067. return false;
  1068. }
  1069. /**
  1070. * Returns {@code true} if the given {@link ByteBuf} is encrypted. Be aware that this method
  1071. * will not increase the readerIndex of the given {@link ByteBuf}.
  1072. *
  1073. * @param buffer
  1074. * The {@link ByteBuf} to read from. Be aware that it must have at least 5 bytes to read,
  1075. * otherwise it will throw an {@link IllegalArgumentException}.
  1076. * @return encrypted
  1077. * {@code true} if the {@link ByteBuf} is encrypted, {@code false} otherwise.
  1078. * @throws IllegalArgumentException
  1079. * Is thrown if the given {@link ByteBuf} has not at least 5 bytes to read.
  1080. */
  1081. public static boolean isEncrypted(ByteBuf buffer) {
  1082. if (buffer.readableBytes() < SslUtils.SSL_RECORD_HEADER_LENGTH) {
  1083. throw new IllegalArgumentException(
  1084. "buffer must have at least " + SslUtils.SSL_RECORD_HEADER_LENGTH + " readable bytes");
  1085. }
  1086. return getEncryptedPacketLength(buffer, buffer.readerIndex()) != SslUtils.NOT_ENCRYPTED;
  1087. }
  1088. private void decodeJdkCompatible(ChannelHandlerContext ctx, ByteBuf in) throws NotSslRecordException {
  1089. int packetLength = this.packetLength;
  1090. // If we calculated the length of the current SSL record before, use that information.
  1091. if (packetLength > 0) {
  1092. if (in.readableBytes() < packetLength) {
  1093. return;
  1094. }
  1095. } else {
  1096. // Get the packet length and wait until we get a packets worth of data to unwrap.
  1097. final int readableBytes = in.readableBytes();
  1098. if (readableBytes < SslUtils.SSL_RECORD_HEADER_LENGTH) {
  1099. return;
  1100. }
  1101. packetLength = getEncryptedPacketLength(in, in.readerIndex());
  1102. if (packetLength == SslUtils.NOT_ENCRYPTED) {
  1103. // Not an SSL/TLS packet
  1104. NotSslRecordException e = new NotSslRecordException(
  1105. "not an SSL/TLS record: " + ByteBufUtil.hexDump(in));
  1106. in.skipBytes(in.readableBytes());
  1107. // First fail the handshake promise as we may need to have access to the SSLEngine which may
  1108. // be released because the user will remove the SslHandler in an exceptionCaught(...) implementation.
  1109. setHandshakeFailure(ctx, e);
  1110. throw e;
  1111. }
  1112. assert packetLength > 0;
  1113. if (packetLength > readableBytes) {
  1114. // wait until the whole packet can be read
  1115. this.packetLength = packetLength;
  1116. return;
  1117. }
  1118. }
  1119. // Reset the state of this class so we can get the length of the next packet. We assume the entire packet will
  1120. // be consumed by the SSLEngine.
  1121. this.packetLength = 0;
  1122. try {
  1123. final int bytesConsumed = unwrap(ctx, in, packetLength);
  1124. assert bytesConsumed == packetLength || engine.isInboundDone() :
  1125. "we feed the SSLEngine a packets worth of data: " + packetLength + " but it only consumed: " +
  1126. bytesConsumed;
  1127. } catch (Throwable cause) {
  1128. handleUnwrapThrowable(ctx, cause);
  1129. }
  1130. }
  1131. private void decodeNonJdkCompatible(ChannelHandlerContext ctx, ByteBuf in) {
  1132. try {
  1133. unwrap(ctx, in, in.readableBytes());
  1134. } catch (Throwable cause) {
  1135. handleUnwrapThrowable(ctx, cause);
  1136. }
  1137. }
  1138. private void handleUnwrapThrowable(ChannelHandlerContext ctx, Throwable cause) {
  1139. try {
  1140. // We should attempt to notify the handshake failure before writing any pending data. If we are in unwrap
  1141. // and failed during the handshake process, and we attempt to wrap, then promises will fail, and if
  1142. // listeners immediately close the Channel then we may end up firing the handshake event after the Channel
  1143. // has been closed.
  1144. if (handshakePromise.tryFailure(cause)) {
  1145. ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(cause));
  1146. }
  1147. // Let's check if the handler was removed in the meantime and so pendingUnencryptedWrites is null.
  1148. if (pendingUnencryptedWrites != null) {
  1149. // We need to flush one time as there may be an alert that we should send to the remote peer because
  1150. // of the SSLException reported here.
  1151. wrapAndFlush(ctx);
  1152. }
  1153. } catch (SSLException ex) {
  1154. logger.debug("SSLException during trying to call SSLEngine.wrap(...)" +
  1155. " because of an previous SSLException, ignoring...", ex);
  1156. } finally {
  1157. // ensure we always flush and close the channel.
  1158. setHandshakeFailure(ctx, cause, true, false, true);
  1159. }
  1160. PlatformDependent.throwException(cause);
  1161. }
  1162. @Override
  1163. protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws SSLException {
  1164. if (isStateSet(STATE_PROCESS_TASK)) {
  1165. return;
  1166. }
  1167. if (jdkCompatibilityMode) {
  1168. decodeJdkCompatible(ctx, in);
  1169. } else {
  1170. decodeNonJdkCompatible(ctx, in);
  1171. }
  1172. }
  1173. @Override
  1174. public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
  1175. channelReadComplete0(ctx);
  1176. }
  1177. private void channelReadComplete0(ChannelHandlerContext ctx) {
  1178. // Discard bytes of the cumulation buffer if needed.
  1179. discardSomeReadBytes();
  1180. flushIfNeeded(ctx);
  1181. readIfNeeded(ctx);
  1182. clearState(STATE_FIRE_CHANNEL_READ);
  1183. ctx.fireChannelReadComplete();
  1184. }
  1185. private void readIfNeeded(ChannelHandlerContext ctx) {
  1186. // If handshake is not finished yet, we need more data.
  1187. if (!ctx.channel().config().isAutoRead() &&
  1188. (!isStateSet(STATE_FIRE_CHANNEL_READ) || !handshakePromise.isDone())) {
  1189. // No auto-read used and no message passed through the ChannelPipeline or the handshake was not complete
  1190. // yet, which means we need to trigger the read to ensure we not encounter any stalls.
  1191. ctx.read();
  1192. }
  1193. }
  1194. private void flushIfNeeded(ChannelHandlerContext ctx) {
  1195. if (isStateSet(STATE_NEEDS_FLUSH)) {
  1196. forceFlush(ctx);
  1197. }
  1198. }
  1199. /**
  1200. * Calls {@link SSLEngine#unwrap(ByteBuffer, ByteBuffer)} with an empty buffer to handle handshakes, etc.
  1201. */
  1202. private int unwrapNonAppData(ChannelHandlerContext ctx) throws SSLException {
  1203. return unwrap(ctx, Unpooled.EMPTY_BUFFER, 0);
  1204. }
  1205. /**
  1206. * Unwraps inbound SSL records.
  1207. */
  1208. private int unwrap(ChannelHandlerContext ctx, ByteBuf packet, int length) throws SSLException {
  1209. final int originalLength = length;
  1210. boolean wrapLater = false;
  1211. boolean notifyClosure = false;
  1212. boolean executedRead = false;
  1213. ByteBuf decodeOut = allocate(ctx, length);
  1214. try {
  1215. // Only continue to loop if the handler was not removed in the meantime.
  1216. // See https://github.com/netty/netty/issues/5860
  1217. do {
  1218. final SSLEngineResult result = engineType.unwrap(this, packet, length, decodeOut);
  1219. final Status status = result.getStatus();
  1220. final HandshakeStatus handshakeStatus = result.getHandshakeStatus();
  1221. final int produced = result.bytesProduced();
  1222. final int consumed = result.bytesConsumed();
  1223. // Skip bytes now in case unwrap is called in a re-entry scenario. For example LocalChannel.read()
  1224. // may entry this method in a re-entry fashion and if the peer is writing into a shared buffer we may
  1225. // unwrap the same data multiple times.
  1226. packet.skipBytes(consumed);
  1227. length -= consumed;
  1228. // The expected sequence of events is:
  1229. // 1. Notify of handshake success
  1230. // 2. fireChannelRead for unwrapped data
  1231. if (handshakeStatus == HandshakeStatus.FINISHED || handshakeStatus == HandshakeStatus.NOT_HANDSHAKING) {
  1232. wrapLater |= (decodeOut.isReadable() ?
  1233. setHandshakeSuccessUnwrapMarkReentry() : setHandshakeSuccess()) ||
  1234. handshakeStatus == HandshakeStatus.FINISHED;
  1235. }
  1236. // Dispatch decoded data after we have notified of handshake success. If this method has been invoked
  1237. // in a re-entry fashion we execute a task on the executor queue to process after the stack unwinds
  1238. // to preserve order of events.
  1239. if (decodeOut.isReadable()) {
  1240. setState(STATE_FIRE_CHANNEL_READ);
  1241. if (isStateSet(STATE_UNWRAP_REENTRY)) {
  1242. executedRead = true;
  1243. executeChannelRead(ctx, decodeOut);
  1244. } else {
  1245. ctx.fireChannelRead(decodeOut);
  1246. }
  1247. decodeOut = null;
  1248. }
  1249. if (status == Status.CLOSED) {
  1250. notifyClosure = true; // notify about the CLOSED state of the SSLEngine. See #137
  1251. } else if (status == Status.BUFFER_OVERFLOW) {
  1252. if (decodeOut != null) {
  1253. decodeOut.release();
  1254. }
  1255. final int applicationBufferSize = engine.getSession().getApplicationBufferSize();
  1256. // Allocate a new buffer which can hold all the rest data and loop again.
  1257. // It may happen that applicationBufferSize < produced while there is still more to unwrap, in this
  1258. // case we will just allocate a new buffer with the capacity of applicationBufferSize and call
  1259. // unwrap again.
  1260. decodeOut = allocate(ctx, engineType.calculatePendingData(this, applicationBufferSize < produced ?
  1261. applicationBufferSize : applicationBufferSize - produced));
  1262. continue;
  1263. }
  1264. if (handshakeStatus == HandshakeStatus.NEED_TASK) {
  1265. boolean pending = runDelegatedTasks(true);
  1266. if (!pending) {
  1267. // We scheduled a task on the delegatingTaskExecutor, so stop processing as we will
  1268. // resume once the task completes.
  1269. //
  1270. // We break out of the loop only and do NOT return here as we still may need to notify
  1271. // about the closure of the SSLEngine.
  1272. wrapLater = false;
  1273. break;
  1274. }
  1275. } else if (handshakeStatus == HandshakeStatus.NEED_WRAP) {
  1276. // If the wrap operation transitions the status to NOT_HANDSHAKING and there is no more data to
  1277. // unwrap then the next call to unwrap will not produce any data. We can avoid the potentially
  1278. // costly unwrap operation and break out of the loop.
  1279. if (wrapNonAppData(ctx, true) && length == 0) {
  1280. break;
  1281. }
  1282. }
  1283. if (status == Status.BUFFER_UNDERFLOW ||
  1284. // If we processed NEED_TASK we should try again even we did not consume or produce anything.
  1285. handshakeStatus != HandshakeStatus.NEED_TASK && (consumed == 0 && produced == 0 ||
  1286. (length == 0 && handshakeStatus == HandshakeStatus.NOT_HANDSHAKING))) {
  1287. if (handshakeStatus == HandshakeStatus.NEED_UNWRAP) {
  1288. // The underlying engine is starving so we need to feed it with more data.
  1289. // See https://github.com/netty/netty/pull/5039
  1290. readIfNeeded(ctx);
  1291. }
  1292. break;
  1293. } else if (decodeOut == null) {
  1294. decodeOut = allocate(ctx, length);
  1295. }
  1296. } while (!ctx.isRemoved());
  1297. if (isStateSet(STATE_FLUSHED_BEFORE_HANDSHAKE) && handshakePromise.isDone()) {
  1298. // We need to call wrap(...) in case there was a flush done before the handshake completed to ensure
  1299. // we do not stale.
  1300. //
  1301. // See https://github.com/netty/netty/pull/2437
  1302. clearState(STATE_FLUSHED_BEFORE_HANDSHAKE);
  1303. wrapLater = true;
  1304. }
  1305. if (wrapLater) {
  1306. wrap(ctx, true);
  1307. }
  1308. } finally {
  1309. if (decodeOut != null) {
  1310. decodeOut.release();
  1311. }
  1312. if (notifyClosure) {
  1313. if (executedRead) {
  1314. executeNotifyClosePromise(ctx);
  1315. } else {
  1316. notifyClosePromise(null);
  1317. }
  1318. }
  1319. }
  1320. return originalLength - length;
  1321. }
  1322. private boolean setHandshakeSuccessUnwrapMarkReentry() {
  1323. // setHandshakeSuccess calls out to external methods which may trigger re-entry. We need to preserve ordering of
  1324. // fireChannelRead for decodeOut relative to re-entry data.
  1325. final boolean setReentryState = !isStateSet(STATE_UNWRAP_REENTRY);
  1326. if (setReentryState) {
  1327. setState(STATE_UNWRAP_REENTRY);
  1328. }
  1329. try {
  1330. return setHandshakeSuccess();
  1331. } finally {
  1332. // It is unlikely this specific method will be re-entry because handshake completion is infrequent, but just
  1333. // in case we only clear the state if we set it in the first place.
  1334. if (setReentryState) {
  1335. clearState(STATE_UNWRAP_REENTRY);
  1336. }
  1337. }
  1338. }
  1339. private void executeNotifyClosePromise(final ChannelHandlerContext ctx) {
  1340. try {
  1341. ctx.executor().execute(new Runnable() {
  1342. @Override
  1343. public void run() {
  1344. notifyClosePromise(null);
  1345. }
  1346. });
  1347. } catch (RejectedExecutionException e) {
  1348. notifyClosePromise(e);
  1349. }
  1350. }
  1351. private void executeChannelRead(final ChannelHandlerContext ctx, final ByteBuf decodedOut) {
  1352. try {
  1353. ctx.executor().execute(new Runnable() {
  1354. @Override
  1355. public void run() {
  1356. ctx.fireChannelRead(decodedOut);
  1357. }
  1358. });
  1359. } catch (RejectedExecutionException e) {
  1360. decodedOut.release();
  1361. throw e;
  1362. }
  1363. }
  1364. private static ByteBuffer toByteBuffer(ByteBuf out, int index, int len) {
  1365. return out.nioBufferCount() == 1 ? out.internalNioBuffer(index, len) :
  1366. out.nioBuffer(index, len);
  1367. }
  1368. private static boolean inEventLoop(Executor executor) {
  1369. return executor instanceof EventExecutor && ((EventExecutor) executor).inEventLoop();
  1370. }
  1371. /**
  1372. * Will either run the delegated task directly calling {@link Runnable#run()} and return {@code true} or will
  1373. * offload the delegated task using {@link Executor#execute(Runnable)} and return {@code false}.
  1374. *
  1375. * If the task is offloaded it will take care to resume its work on the {@link EventExecutor} once there are no
  1376. * more tasks to process.
  1377. */
  1378. private boolean runDelegatedTasks(boolean inUnwrap) {
  1379. if (delegatedTaskExecutor == ImmediateExecutor.INSTANCE || inEventLoop(delegatedTaskExecutor)) {
  1380. // We should run the task directly in the EventExecutor thread and not offload at all. As we are on the
  1381. // EventLoop we can just run all tasks at once.
  1382. for (;;) {
  1383. Runnable task = engine.getDelegatedTask();
  1384. if (task == null) {
  1385. return true;
  1386. }
  1387. setState(STATE_PROCESS_TASK);
  1388. if (task instanceof AsyncRunnable) {
  1389. // Let's set the task to processing task before we try to execute it.
  1390. boolean pending = false;
  1391. try {
  1392. AsyncRunnable asyncTask = (AsyncRunnable) task;
  1393. AsyncTaskCompletionHandler completionHandler = new AsyncTaskCompletionHandler(inUnwrap);
  1394. asyncTask.run(completionHandler);
  1395. pending = completionHandler.resumeLater();
  1396. if (pending) {
  1397. return false;
  1398. }
  1399. } finally {
  1400. if (!pending) {
  1401. // The task has completed, lets clear the state. If it is not completed we will clear the
  1402. // state once it is.
  1403. clearState(STATE_PROCESS_TASK);
  1404. }
  1405. }
  1406. } else {
  1407. try {
  1408. task.run();
  1409. } finally {
  1410. clearState(STATE_PROCESS_TASK);
  1411. }
  1412. }
  1413. }
  1414. } else {
  1415. executeDelegatedTask(inUnwrap);
  1416. return false;
  1417. }
  1418. }
  1419. private SslTasksRunner getTaskRunner(boolean inUnwrap) {
  1420. return inUnwrap ? sslTaskRunnerForUnwrap : sslTaskRunner;
  1421. }
  1422. private void executeDelegatedTask(boolean inUnwrap) {
  1423. executeDelegatedTask(getTaskRunner(inUnwrap));
  1424. }
  1425. private void executeDelegatedTask(SslTasksRunner task) {
  1426. setState(STATE_PROCESS_TASK);
  1427. try {
  1428. delegatedTaskExecutor.execute(task);
  1429. } catch (RejectedExecutionException e) {
  1430. clearState(STATE_PROCESS_TASK);
  1431. throw e;
  1432. }
  1433. }
  1434. private final class AsyncTaskCompletionHandler implements Runnable {
  1435. private final boolean inUnwrap;
  1436. boolean didRun;
  1437. boolean resumeLater;
  1438. AsyncTaskCompletionHandler(boolean inUnwrap) {
  1439. this.inUnwrap = inUnwrap;
  1440. }
  1441. @Override
  1442. public void run() {
  1443. didRun = true;
  1444. if (resumeLater) {
  1445. getTaskRunner(inUnwrap).runComplete();
  1446. }
  1447. }
  1448. boolean resumeLater() {
  1449. if (!didRun) {
  1450. resumeLater = true;
  1451. return true;
  1452. }
  1453. return false;
  1454. }
  1455. }
  1456. /**
  1457. * {@link Runnable} that will be scheduled on the {@code delegatedTaskExecutor} and will take care
  1458. * of resume work on the {@link EventExecutor} once the task was executed.
  1459. */
  1460. private final class SslTasksRunner implements Runnable {
  1461. private final boolean inUnwrap;
  1462. private final Runnable runCompleteTask = new Runnable() {
  1463. @Override
  1464. public void run() {
  1465. runComplete();
  1466. }
  1467. };
  1468. SslTasksRunner(boolean inUnwrap) {
  1469. this.inUnwrap = inUnwrap;
  1470. }
  1471. // Handle errors which happened during task processing.
  1472. private void taskError(Throwable e) {
  1473. if (inUnwrap) {
  1474. // As the error happened while the task was scheduled as part of unwrap(...) we also need to ensure
  1475. // we fire it through the pipeline as inbound error to be consistent with what we do in decode(...).
  1476. //
  1477. // This will also ensure we fail the handshake future and flush all produced data.
  1478. try {
  1479. handleUnwrapThrowable(ctx, e);
  1480. } catch (Throwable cause) {
  1481. safeExceptionCaught(cause);
  1482. }
  1483. } else {
  1484. setHandshakeFailure(ctx, e);
  1485. forceFlush(ctx);
  1486. }
  1487. }
  1488. // Try to call exceptionCaught(...)
  1489. private void safeExceptionCaught(Throwable cause) {
  1490. try {
  1491. exceptionCaught(ctx, wrapIfNeeded(cause));
  1492. } catch (Throwable error) {
  1493. ctx.fireExceptionCaught(error);
  1494. }
  1495. }
  1496. private Throwable wrapIfNeeded(Throwable cause) {
  1497. if (!inUnwrap) {
  1498. // If we are not in unwrap(...) we can just rethrow without wrapping at all.
  1499. return cause;
  1500. }
  1501. // As the exception would have been triggered by an inbound operation we will need to wrap it in a
  1502. // DecoderException to mimic what a decoder would do when decode(...) throws.
  1503. return cause instanceof DecoderException ? cause : new DecoderException(cause);
  1504. }
  1505. private void tryDecodeAgain() {
  1506. try {
  1507. channelRead(ctx, Unpooled.EMPTY_BUFFER);
  1508. } catch (Throwable cause) {
  1509. safeExceptionCaught(cause);
  1510. } finally {
  1511. // As we called channelRead(...) we also need to call channelReadComplete(...) which
  1512. // will ensure we either call ctx.fireChannelReadComplete() or will trigger a ctx.read() if
  1513. // more data is needed.
  1514. channelReadComplete0(ctx);
  1515. }
  1516. }
  1517. /**
  1518. * Executed after the wrapped {@code task} was executed via {@code delegatedTaskExecutor} to resume work
  1519. * on the {@link EventExecutor}.
  1520. */
  1521. private void resumeOnEventExecutor() {
  1522. assert ctx.executor().inEventLoop();
  1523. clearState(STATE_PROCESS_TASK);
  1524. try {
  1525. HandshakeStatus status = engine.getHandshakeStatus();
  1526. switch (status) {
  1527. // There is another task that needs to be executed and offloaded to the delegatingTaskExecutor as
  1528. // a result of this. Let's reschedule....
  1529. case NEED_TASK:
  1530. executeDelegatedTask(this);
  1531. break;
  1532. // The handshake finished, lets notify about the completion of it and resume processing.
  1533. case FINISHED:
  1534. // Not handshaking anymore, lets notify about the completion if not done yet and resume processing.
  1535. case NOT_HANDSHAKING:
  1536. setHandshakeSuccess(); // NOT_HANDSHAKING -> workaround for android skipping FINISHED state.
  1537. try {
  1538. // Lets call wrap to ensure we produce the alert if there is any pending and also to
  1539. // ensure we flush any queued data..
  1540. wrap(ctx, inUnwrap);
  1541. } catch (Throwable e) {
  1542. taskError(e);
  1543. return;
  1544. }
  1545. if (inUnwrap) {
  1546. // If we were in the unwrap call when the task was processed we should also try to unwrap
  1547. // non app data first as there may not anything left in the inbound buffer to process.
  1548. unwrapNonAppData(ctx);
  1549. }
  1550. // Flush now as we may have written some data as part of the wrap call.
  1551. forceFlush(ctx);
  1552. tryDecodeAgain();
  1553. break;
  1554. // We need more data so lets try to unwrap first and then call decode again which will feed us
  1555. // with buffered data (if there is any).
  1556. case NEED_UNWRAP:
  1557. try {
  1558. unwrapNonAppData(ctx);
  1559. } catch (SSLException e) {
  1560. handleUnwrapThrowable(ctx, e);
  1561. return;
  1562. }
  1563. tryDecodeAgain();
  1564. break;
  1565. // To make progress we need to call SSLEngine.wrap(...) which may produce more output data
  1566. // that will be written to the Channel.
  1567. case NEED_WRAP:
  1568. try {
  1569. if (!wrapNonAppData(ctx, false) && inUnwrap) {
  1570. // The handshake finished in wrapNonAppData(...), we need to try call
  1571. // unwrapNonAppData(...) as we may have some alert that we should read.
  1572. //
  1573. // This mimics what we would do when we are calling this method while in unwrap(...).
  1574. unwrapNonAppData(ctx);
  1575. }
  1576. // Flush now as we may have written some data as part of the wrap call.
  1577. forceFlush(ctx);
  1578. } catch (Throwable e) {
  1579. taskError(e);
  1580. return;
  1581. }
  1582. // Now try to feed in more data that we have buffered.
  1583. tryDecodeAgain();
  1584. break;
  1585. default:
  1586. // Should never reach here as we handle all cases.
  1587. throw new AssertionError();
  1588. }
  1589. } catch (Throwable cause) {
  1590. safeExceptionCaught(cause);
  1591. }
  1592. }
  1593. void runComplete() {
  1594. EventExecutor executor = ctx.executor();
  1595. if (executor.inEventLoop()) {
  1596. resumeOnEventExecutor();
  1597. } else {
  1598. // Jump back on the EventExecutor.
  1599. executor.execute(new Runnable() {
  1600. @Override
  1601. public void run() {
  1602. resumeOnEventExecutor();
  1603. }
  1604. });
  1605. }
  1606. }
  1607. @Override
  1608. public void run() {
  1609. try {
  1610. Runnable task = engine.getDelegatedTask();
  1611. if (task == null) {
  1612. // The task was processed in the meantime. Let's just return.
  1613. return;
  1614. }
  1615. if (task instanceof AsyncRunnable) {
  1616. AsyncRunnable asyncTask = (AsyncRunnable) task;
  1617. asyncTask.run(runCompleteTask);
  1618. } else {
  1619. task.run();
  1620. runComplete();
  1621. }
  1622. } catch (final Throwable cause) {
  1623. handleException(cause);
  1624. }
  1625. }
  1626. private void handleException(final Throwable cause) {
  1627. EventExecutor executor = ctx.executor();
  1628. if (executor.inEventLoop()) {
  1629. clearState(STATE_PROCESS_TASK);
  1630. safeExceptionCaught(cause);
  1631. } else {
  1632. try {
  1633. executor.execute(new Runnable() {
  1634. @Override
  1635. public void run() {
  1636. clearState(STATE_PROCESS_TASK);
  1637. safeExceptionCaught(cause);
  1638. }
  1639. });
  1640. } catch (RejectedExecutionException ignore) {
  1641. clearState(STATE_PROCESS_TASK);
  1642. // the context itself will handle the rejected exception when try to schedule the operation so
  1643. // ignore the RejectedExecutionException
  1644. ctx.fireExceptionCaught(cause);
  1645. }
  1646. }
  1647. }
  1648. }
  1649. /**
  1650. * Notify all the handshake futures about the successfully handshake
  1651. * @return {@code true} if {@link #handshakePromise} was set successfully and a {@link SslHandshakeCompletionEvent}
  1652. * was fired. {@code false} otherwise.
  1653. */
  1654. private boolean setHandshakeSuccess() {
  1655. // Our control flow may invoke this method multiple times for a single FINISHED event. For example
  1656. // wrapNonAppData may drain pendingUnencryptedWrites in wrap which transitions to handshake from FINISHED to
  1657. // NOT_HANDSHAKING which invokes setHandshakeSuccess, and then wrapNonAppData also directly invokes this method.
  1658. final boolean notified;
  1659. if (notified = !handshakePromise.isDone() && handshakePromise.trySuccess(ctx.channel())) {
  1660. if (logger.isDebugEnabled()) {
  1661. SSLSession session = engine.getSession();
  1662. logger.debug(
  1663. "{} HANDSHAKEN: protocol:{} cipher suite:{}",
  1664. ctx.channel(),
  1665. session.getProtocol(),
  1666. session.getCipherSuite());
  1667. }
  1668. ctx.fireUserEventTriggered(SslHandshakeCompletionEvent.SUCCESS);
  1669. }
  1670. if (isStateSet(STATE_READ_DURING_HANDSHAKE)) {
  1671. clearState(STATE_READ_DURING_HANDSHAKE);
  1672. if (!ctx.channel().config().isAutoRead()) {
  1673. ctx.read();
  1674. }
  1675. }
  1676. return notified;
  1677. }
  1678. /**
  1679. * Notify all the handshake futures about the failure during the handshake.
  1680. */
  1681. private void setHandshakeFailure(ChannelHandlerContext ctx, Throwable cause) {
  1682. setHandshakeFailure(ctx, cause, true, true, false);
  1683. }
  1684. /**
  1685. * Notify all the handshake futures about the failure during the handshake.
  1686. */
  1687. private void setHandshakeFailure(ChannelHandlerContext ctx, Throwable cause, boolean closeInbound,
  1688. boolean notify, boolean alwaysFlushAndClose) {
  1689. try {
  1690. // Release all resources such as internal buffers that SSLEngine is managing.
  1691. setState(STATE_OUTBOUND_CLOSED);
  1692. engine.closeOutbound();
  1693. if (closeInbound) {
  1694. try {
  1695. engine.closeInbound();
  1696. } catch (SSLException e) {
  1697. if (logger.isDebugEnabled()) {
  1698. // only log in debug mode as it most likely harmless and latest chrome still trigger
  1699. // this all the time.
  1700. //
  1701. // See https://github.com/netty/netty/issues/1340
  1702. String msg = e.getMessage();
  1703. if (msg == null || !(msg.contains("possible truncation attack") ||
  1704. msg.contains("closing inbound before receiving peer's close_notify"))) {
  1705. logger.debug("{} SSLEngine.closeInbound() raised an exception.", ctx.channel(), e);
  1706. }
  1707. }
  1708. }
  1709. }
  1710. if (handshakePromise.tryFailure(cause) || alwaysFlushAndClose) {
  1711. SslUtils.handleHandshakeFailure(ctx, cause, notify);
  1712. }
  1713. } finally {
  1714. // Ensure we remove and fail all pending writes in all cases and so release memory quickly.
  1715. releaseAndFailAll(ctx, cause);
  1716. }
  1717. }
  1718. private void setHandshakeFailureTransportFailure(ChannelHandlerContext ctx, Throwable cause) {
  1719. // If TLS control frames fail to write we are in an unknown state and may become out of
  1720. // sync with our peer. We give up and close the channel. This will also take care of
  1721. // cleaning up any outstanding state (e.g. handshake promise, queued unencrypted data).
  1722. try {
  1723. SSLException transportFailure = new SSLException("failure when writing TLS control frames", cause);
  1724. releaseAndFailAll(ctx, transportFailure);
  1725. if (handshakePromise.tryFailure(transportFailure)) {
  1726. ctx.fireUserEventTriggered(new SslHandshakeCompletionEvent(transportFailure));
  1727. }
  1728. } finally {
  1729. ctx.close();
  1730. }
  1731. }
  1732. private void releaseAndFailAll(ChannelHandlerContext ctx, Throwable cause) {
  1733. if (pendingUnencryptedWrites != null) {
  1734. pendingUnencryptedWrites.releaseAndFailAll(ctx, cause);
  1735. }
  1736. }
  1737. private void notifyClosePromise(Throwable cause) {
  1738. if (cause == null) {
  1739. if (sslClosePromise.trySuccess(ctx.channel())) {
  1740. ctx.fireUserEventTriggered(SslCloseCompletionEvent.SUCCESS);
  1741. }
  1742. } else {
  1743. if (sslClosePromise.tryFailure(cause)) {
  1744. ctx.fireUserEventTriggered(new SslCloseCompletionEvent(cause));
  1745. }
  1746. }
  1747. }
  1748. private void closeOutboundAndChannel(
  1749. final ChannelHandlerContext ctx, final ChannelPromise promise, boolean disconnect) throws Exception {
  1750. setState(STATE_OUTBOUND_CLOSED);
  1751. engine.closeOutbound();
  1752. if (!ctx.channel().isActive()) {
  1753. if (disconnect) {
  1754. ctx.disconnect(promise);
  1755. } else {
  1756. ctx.close(promise);
  1757. }
  1758. return;
  1759. }
  1760. ChannelPromise closeNotifyPromise = ctx.newPromise();
  1761. try {
  1762. flush(ctx, closeNotifyPromise);
  1763. } finally {
  1764. if (!isStateSet(STATE_CLOSE_NOTIFY)) {
  1765. setState(STATE_CLOSE_NOTIFY);
  1766. // It's important that we do not pass the original ChannelPromise to safeClose(...) as when flush(....)
  1767. // throws an Exception it will be propagated to the AbstractChannelHandlerContext which will try
  1768. // to fail the promise because of this. This will then fail as it was already completed by
  1769. // safeClose(...). We create a new ChannelPromise and try to notify the original ChannelPromise
  1770. // once it is complete. If we fail to do so we just ignore it as in this case it was failed already
  1771. // because of a propagated Exception.
  1772. //
  1773. // See https://github.com/netty/netty/issues/5931
  1774. safeClose(ctx, closeNotifyPromise, PromiseNotifier.cascade(false, ctx.newPromise(), promise));
  1775. } else {
  1776. /// We already handling the close_notify so just attach the promise to the sslClosePromise.
  1777. sslClosePromise.addListener(new FutureListener<Channel>() {
  1778. @Override
  1779. public void operationComplete(Future<Channel> future) {
  1780. promise.setSuccess();
  1781. }
  1782. });
  1783. }
  1784. }
  1785. }
  1786. private void flush(ChannelHandlerContext ctx, ChannelPromise promise) throws Exception {
  1787. if (pendingUnencryptedWrites != null) {
  1788. pendingUnencryptedWrites.add(Unpooled.EMPTY_BUFFER, promise);
  1789. } else {
  1790. promise.setFailure(newPendingWritesNullException());
  1791. }
  1792. flush(ctx);
  1793. }
  1794. @Override
  1795. public void handlerAdded(final ChannelHandlerContext ctx) throws Exception {
  1796. this.ctx = ctx;
  1797. Channel channel = ctx.channel();
  1798. pendingUnencryptedWrites = new SslHandlerCoalescingBufferQueue(channel, 16);
  1799. boolean fastOpen = Boolean.TRUE.equals(channel.config().getOption(ChannelOption.TCP_FASTOPEN_CONNECT));
  1800. boolean active = channel.isActive();
  1801. if (active || fastOpen) {
  1802. // Explicitly flush the handshake only if the channel is already active.
  1803. // With TCP Fast Open, we write to the outbound buffer before the TCP connect is established.
  1804. // The buffer will then be flushed as part of establishing the connection, saving us a round-trip.
  1805. startHandshakeProcessing(active);
  1806. // If we weren't able to include client_hello in the TCP SYN (e.g. no token, disabled at the OS) we have to
  1807. // flush pending data in the outbound buffer later in channelActive().
  1808. final ChannelOutboundBuffer outboundBuffer;
  1809. if (fastOpen && ((outboundBuffer = channel.unsafe().outboundBuffer()) == null ||
  1810. outboundBuffer.totalPendingWriteBytes() > 0)) {
  1811. setState(STATE_NEEDS_FLUSH);
  1812. }
  1813. }
  1814. }
  1815. private void startHandshakeProcessing(boolean flushAtEnd) {
  1816. if (!isStateSet(STATE_HANDSHAKE_STARTED)) {
  1817. setState(STATE_HANDSHAKE_STARTED);
  1818. if (engine.getUseClientMode()) {
  1819. // Begin the initial handshake.
  1820. // channelActive() event has been fired already, which means this.channelActive() will
  1821. // not be invoked. We have to initialize here instead.
  1822. handshake(flushAtEnd);
  1823. }
  1824. applyHandshakeTimeout();
  1825. } else if (isStateSet(STATE_NEEDS_FLUSH)) {
  1826. forceFlush(ctx);
  1827. }
  1828. }
  1829. /**
  1830. * Performs TLS renegotiation.
  1831. */
  1832. public Future<Channel> renegotiate() {
  1833. ChannelHandlerContext ctx = this.ctx;
  1834. if (ctx == null) {
  1835. throw new IllegalStateException();
  1836. }
  1837. return renegotiate(ctx.executor().<Channel>newPromise());
  1838. }
  1839. /**
  1840. * Performs TLS renegotiation.
  1841. */
  1842. public Future<Channel> renegotiate(final Promise<Channel> promise) {
  1843. ObjectUtil.checkNotNull(promise, "promise");
  1844. ChannelHandlerContext ctx = this.ctx;
  1845. if (ctx == null) {
  1846. throw new IllegalStateException();
  1847. }
  1848. EventExecutor executor = ctx.executor();
  1849. if (!executor.inEventLoop()) {
  1850. executor.execute(new Runnable() {
  1851. @Override
  1852. public void run() {
  1853. renegotiateOnEventLoop(promise);
  1854. }
  1855. });
  1856. return promise;
  1857. }
  1858. renegotiateOnEventLoop(promise);
  1859. return promise;
  1860. }
  1861. private void renegotiateOnEventLoop(final Promise<Channel> newHandshakePromise) {
  1862. final Promise<Channel> oldHandshakePromise = handshakePromise;
  1863. if (!oldHandshakePromise.isDone()) {
  1864. // There's no need to handshake because handshake is in progress already.
  1865. // Merge the new promise into the old one.
  1866. PromiseNotifier.cascade(oldHandshakePromise, newHandshakePromise);
  1867. } else {
  1868. handshakePromise = newHandshakePromise;
  1869. handshake(true);
  1870. applyHandshakeTimeout();
  1871. }
  1872. }
  1873. /**
  1874. * Performs TLS (re)negotiation.
  1875. * @param flushAtEnd Set to {@code true} if the outbound buffer should be flushed (written to the network) at the
  1876. * end. Set to {@code false} if the handshake will be flushed later, e.g. as part of TCP Fast Open
  1877. * connect.
  1878. */
  1879. private void handshake(boolean flushAtEnd) {
  1880. if (engine.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING) {
  1881. // Not all SSLEngine implementations support calling beginHandshake multiple times while a handshake
  1882. // is in progress. See https://github.com/netty/netty/issues/4718.
  1883. return;
  1884. }
  1885. if (handshakePromise.isDone()) {
  1886. // If the handshake is done already lets just return directly as there is no need to trigger it again.
  1887. // This can happen if the handshake(...) was triggered before we called channelActive(...) by a
  1888. // flush() that was triggered by a ChannelFutureListener that was added to the ChannelFuture returned
  1889. // from the connect(...) method. In this case we will see the flush() happen before we had a chance to
  1890. // call fireChannelActive() on the pipeline.
  1891. return;
  1892. }
  1893. // Begin handshake.
  1894. final ChannelHandlerContext ctx = this.ctx;
  1895. try {
  1896. engine.beginHandshake();
  1897. wrapNonAppData(ctx, false);
  1898. } catch (Throwable e) {
  1899. setHandshakeFailure(ctx, e);
  1900. } finally {
  1901. if (flushAtEnd) {
  1902. forceFlush(ctx);
  1903. }
  1904. }
  1905. }
  1906. private void applyHandshakeTimeout() {
  1907. final Promise<Channel> localHandshakePromise = this.handshakePromise;
  1908. // Set timeout if necessary.
  1909. final long handshakeTimeoutMillis = this.handshakeTimeoutMillis;
  1910. if (handshakeTimeoutMillis <= 0 || localHandshakePromise.isDone()) {
  1911. return;
  1912. }
  1913. final Future<?> timeoutFuture = ctx.executor().schedule(new Runnable() {
  1914. @Override
  1915. public void run() {
  1916. if (localHandshakePromise.isDone()) {
  1917. return;
  1918. }
  1919. SSLException exception =
  1920. new SslHandshakeTimeoutException("handshake timed out after " + handshakeTimeoutMillis + "ms");
  1921. try {
  1922. if (localHandshakePromise.tryFailure(exception)) {
  1923. SslUtils.handleHandshakeFailure(ctx, exception, true);
  1924. }
  1925. } finally {
  1926. releaseAndFailAll(ctx, exception);
  1927. }
  1928. }
  1929. }, handshakeTimeoutMillis, TimeUnit.MILLISECONDS);
  1930. // Cancel the handshake timeout when handshake is finished.
  1931. localHandshakePromise.addListener(new FutureListener<Channel>() {
  1932. @Override
  1933. public void operationComplete(Future<Channel> f) throws Exception {
  1934. timeoutFuture.cancel(false);
  1935. }
  1936. });
  1937. }
  1938. private void forceFlush(ChannelHandlerContext ctx) {
  1939. clearState(STATE_NEEDS_FLUSH);
  1940. ctx.flush();
  1941. }
  1942. /**
  1943. * Issues an initial TLS handshake once connected when used in client-mode
  1944. */
  1945. @Override
  1946. public void channelActive(final ChannelHandlerContext ctx) throws Exception {
  1947. if (!startTls) {
  1948. startHandshakeProcessing(true);
  1949. }
  1950. ctx.fireChannelActive();
  1951. }
  1952. private void safeClose(
  1953. final ChannelHandlerContext ctx, final ChannelFuture flushFuture,
  1954. final ChannelPromise promise) {
  1955. if (!ctx.channel().isActive()) {
  1956. ctx.close(promise);
  1957. return;
  1958. }
  1959. final Future<?> timeoutFuture;
  1960. if (!flushFuture.isDone()) {
  1961. long closeNotifyTimeout = closeNotifyFlushTimeoutMillis;
  1962. if (closeNotifyTimeout > 0) {
  1963. // Force-close the connection if close_notify is not fully sent in time.
  1964. timeoutFuture = ctx.executor().schedule(new Runnable() {
  1965. @Override
  1966. public void run() {
  1967. // May be done in the meantime as cancel(...) is only best effort.
  1968. if (!flushFuture.isDone()) {
  1969. logger.warn("{} Last write attempt timed out; force-closing the connection.",
  1970. ctx.channel());
  1971. addCloseListener(ctx.close(ctx.newPromise()), promise);
  1972. }
  1973. }
  1974. }, closeNotifyTimeout, TimeUnit.MILLISECONDS);
  1975. } else {
  1976. timeoutFuture = null;
  1977. }
  1978. } else {
  1979. timeoutFuture = null;
  1980. }
  1981. // Close the connection if close_notify is sent in time.
  1982. flushFuture.addListener(new ChannelFutureListener() {
  1983. @Override
  1984. public void operationComplete(ChannelFuture f) {
  1985. if (timeoutFuture != null) {
  1986. timeoutFuture.cancel(false);
  1987. }
  1988. final long closeNotifyReadTimeout = closeNotifyReadTimeoutMillis;
  1989. if (closeNotifyReadTimeout <= 0) {
  1990. // Trigger the close in all cases to make sure the promise is notified
  1991. // See https://github.com/netty/netty/issues/2358
  1992. addCloseListener(ctx.close(ctx.newPromise()), promise);
  1993. } else {
  1994. final Future<?> closeNotifyReadTimeoutFuture;
  1995. if (!sslClosePromise.isDone()) {
  1996. closeNotifyReadTimeoutFuture = ctx.executor().schedule(new Runnable() {
  1997. @Override
  1998. public void run() {
  1999. if (!sslClosePromise.isDone()) {
  2000. logger.debug(
  2001. "{} did not receive close_notify in {}ms; force-closing the connection.",
  2002. ctx.channel(), closeNotifyReadTimeout);
  2003. // Do the close now...
  2004. addCloseListener(ctx.close(ctx.newPromise()), promise);
  2005. }
  2006. }
  2007. }, closeNotifyReadTimeout, TimeUnit.MILLISECONDS);
  2008. } else {
  2009. closeNotifyReadTimeoutFuture = null;
  2010. }
  2011. // Do the close once the we received the close_notify.
  2012. sslClosePromise.addListener(new FutureListener<Channel>() {
  2013. @Override
  2014. public void operationComplete(Future<Channel> future) throws Exception {
  2015. if (closeNotifyReadTimeoutFuture != null) {
  2016. closeNotifyReadTimeoutFuture.cancel(false);
  2017. }
  2018. addCloseListener(ctx.close(ctx.newPromise()), promise);
  2019. }
  2020. });
  2021. }
  2022. }
  2023. });
  2024. }
  2025. private static void addCloseListener(ChannelFuture future, ChannelPromise promise) {
  2026. // We notify the promise in the ChannelPromiseNotifier as there is a "race" where the close(...) call
  2027. // by the timeoutFuture and the close call in the flushFuture listener will be called. Because of
  2028. // this we need to use trySuccess() and tryFailure(...) as otherwise we can cause an
  2029. // IllegalStateException.
  2030. // Also we not want to log if the notification happens as this is expected in some cases.
  2031. // See https://github.com/netty/netty/issues/5598
  2032. PromiseNotifier.cascade(false, future, promise);
  2033. }
  2034. /**
  2035. * Always prefer a direct buffer when it's pooled, so that we reduce the number of memory copies
  2036. * in {@link OpenSslEngine}.
  2037. */
  2038. private ByteBuf allocate(ChannelHandlerContext ctx, int capacity) {
  2039. ByteBufAllocator alloc = ctx.alloc();
  2040. if (engineType.wantsDirectBuffer) {
  2041. return alloc.directBuffer(capacity);
  2042. } else {
  2043. return alloc.buffer(capacity);
  2044. }
  2045. }
  2046. /**
  2047. * Allocates an outbound network buffer for {@link SSLEngine#wrap(ByteBuffer, ByteBuffer)} which can encrypt
  2048. * the specified amount of pending bytes.
  2049. */
  2050. private ByteBuf allocateOutNetBuf(ChannelHandlerContext ctx, int pendingBytes, int numComponents) {
  2051. return engineType.allocateWrapBuffer(this, ctx.alloc(), pendingBytes, numComponents);
  2052. }
  2053. private boolean isStateSet(int bit) {
  2054. return (state & bit) == bit;
  2055. }
  2056. private void setState(int bit) {
  2057. state |= bit;
  2058. }
  2059. private void clearState(int bit) {
  2060. state &= ~bit;
  2061. }
  2062. /**
  2063. * Each call to SSL_write will introduce about ~100 bytes of overhead. This coalescing queue attempts to increase
  2064. * goodput by aggregating the plaintext in chunks of {@link #wrapDataSize}. If many small chunks are written
  2065. * this can increase goodput, decrease the amount of calls to SSL_write, and decrease overall encryption operations.
  2066. */
  2067. private final class SslHandlerCoalescingBufferQueue extends AbstractCoalescingBufferQueue {
  2068. SslHandlerCoalescingBufferQueue(Channel channel, int initSize) {
  2069. super(channel, initSize);
  2070. }
  2071. @Override
  2072. protected ByteBuf compose(ByteBufAllocator alloc, ByteBuf cumulation, ByteBuf next) {
  2073. final int wrapDataSize = SslHandler.this.wrapDataSize;
  2074. if (cumulation instanceof CompositeByteBuf) {
  2075. CompositeByteBuf composite = (CompositeByteBuf) cumulation;
  2076. int numComponents = composite.numComponents();
  2077. if (numComponents == 0 ||
  2078. !attemptCopyToCumulation(composite.internalComponent(numComponents - 1), next, wrapDataSize)) {
  2079. composite.addComponent(true, next);
  2080. }
  2081. return composite;
  2082. }
  2083. return attemptCopyToCumulation(cumulation, next, wrapDataSize) ? cumulation :
  2084. copyAndCompose(alloc, cumulation, next);
  2085. }
  2086. @Override
  2087. protected ByteBuf composeFirst(ByteBufAllocator allocator, ByteBuf first) {
  2088. if (first instanceof CompositeByteBuf) {
  2089. CompositeByteBuf composite = (CompositeByteBuf) first;
  2090. if (engineType.wantsDirectBuffer) {
  2091. first = allocator.directBuffer(composite.readableBytes());
  2092. } else {
  2093. first = allocator.heapBuffer(composite.readableBytes());
  2094. }
  2095. try {
  2096. first.writeBytes(composite);
  2097. } catch (Throwable cause) {
  2098. first.release();
  2099. PlatformDependent.throwException(cause);
  2100. }
  2101. composite.release();
  2102. }
  2103. return first;
  2104. }
  2105. @Override
  2106. protected ByteBuf removeEmptyValue() {
  2107. return null;
  2108. }
  2109. }
  2110. private static boolean attemptCopyToCumulation(ByteBuf cumulation, ByteBuf next, int wrapDataSize) {
  2111. final int inReadableBytes = next.readableBytes();
  2112. final int cumulationCapacity = cumulation.capacity();
  2113. if (wrapDataSize - cumulation.readableBytes() >= inReadableBytes &&
  2114. // Avoid using the same buffer if next's data would make cumulation exceed the wrapDataSize.
  2115. // Only copy if there is enough space available and the capacity is large enough, and attempt to
  2116. // resize if the capacity is small.
  2117. (cumulation.isWritable(inReadableBytes) && cumulationCapacity >= wrapDataSize ||
  2118. cumulationCapacity < wrapDataSize &&
  2119. ensureWritableSuccess(cumulation.ensureWritable(inReadableBytes, false)))) {
  2120. cumulation.writeBytes(next);
  2121. next.release();
  2122. return true;
  2123. }
  2124. return false;
  2125. }
  2126. private final class LazyChannelPromise extends DefaultPromise<Channel> {
  2127. @Override
  2128. protected EventExecutor executor() {
  2129. if (ctx == null) {
  2130. throw new IllegalStateException();
  2131. }
  2132. return ctx.executor();
  2133. }
  2134. @Override
  2135. protected void checkDeadLock() {
  2136. if (ctx == null) {
  2137. // If ctx is null the handlerAdded(...) callback was not called, in this case the checkDeadLock()
  2138. // method was called from another Thread then the one that is used by ctx.executor(). We need to
  2139. // guard against this as a user can see a race if handshakeFuture().sync() is called but the
  2140. // handlerAdded(..) method was not yet as it is called from the EventExecutor of the
  2141. // ChannelHandlerContext. If we not guard against this super.checkDeadLock() would cause an
  2142. // IllegalStateException when trying to call executor().
  2143. return;
  2144. }
  2145. super.checkDeadLock();
  2146. }
  2147. }
  2148. }