Skip to content

Commit 9970d71

Browse files
authored
Merge pull request #2469 from etspaceman/tlsFix2.5
Fix TLS socket read stall immediately after handshake
2 parents b59bc25 + 4f44b36 commit 9970d71

File tree

1 file changed

+14
-7
lines changed

1 file changed

+14
-7
lines changed

io/src/main/scala/fs2/io/tls/TLSEngine.scala

+14-7
Original file line numberDiff line numberDiff line change
@@ -128,12 +128,13 @@ private[tls] object TLSEngine {
128128

129129
private def read0(maxBytes: Int, timeout: Option[FiniteDuration]): F[Option[Chunk[Byte]]] =
130130
// Check if the initial handshake has finished -- if so, read; otherwise, handshake and then read
131-
dequeueUnwrap(maxBytes).flatMap { out =>
131+
unwrapThenTakeUnwrapped(maxBytes, timeout).flatMap { out =>
132132
if (out.isEmpty)
133133
initialHandshakeDone.ifM(
134134
read1(maxBytes, timeout),
135-
write(Chunk.empty, None) >> dequeueUnwrap(maxBytes).flatMap { out =>
136-
if (out.isEmpty) read1(maxBytes, timeout) else Applicative[F].pure(out)
135+
write(Chunk.empty, None) >> unwrapThenTakeUnwrapped(maxBytes, timeout).flatMap {
136+
out =>
137+
if (out.isEmpty) read1(maxBytes, timeout) else Applicative[F].pure(out)
137138
}
138139
)
139140
else Applicative[F].pure(out)
@@ -161,7 +162,7 @@ private[tls] object TLSEngine {
161162
case SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING =>
162163
unwrapBuffer.inputRemains
163164
.map(_ > 0 && result.bytesConsumed > 0)
164-
.ifM(unwrap(maxBytes, timeout), dequeueUnwrap(maxBytes))
165+
.ifM(unwrap(maxBytes, timeout), takeUnwrapped(maxBytes))
165166
case SSLEngineResult.HandshakeStatus.FINISHED =>
166167
unwrap(maxBytes, timeout)
167168
case _ =>
@@ -172,17 +173,23 @@ private[tls] object TLSEngine {
172173
)
173174
}
174175
case SSLEngineResult.Status.BUFFER_UNDERFLOW =>
175-
dequeueUnwrap(maxBytes)
176+
takeUnwrapped(maxBytes)
176177
case SSLEngineResult.Status.BUFFER_OVERFLOW =>
177178
unwrapBuffer.expandOutput >> unwrap(maxBytes, timeout)
178179
case SSLEngineResult.Status.CLOSED =>
179-
stopWrap >> stopUnwrap >> dequeueUnwrap(maxBytes)
180+
stopWrap >> stopUnwrap >> takeUnwrapped(maxBytes)
180181
}
181182
}
182183

183-
private def dequeueUnwrap(maxBytes: Int): F[Option[Chunk[Byte]]] =
184+
private def takeUnwrapped(maxBytes: Int): F[Option[Chunk[Byte]]] =
184185
unwrapBuffer.output(maxBytes).map(out => if (out.isEmpty) None else Some(out))
185186

187+
private def unwrapThenTakeUnwrapped(
188+
maxBytes: Int,
189+
timeout: Option[FiniteDuration]
190+
): F[Option[Chunk[Byte]]] =
191+
unwrapBuffer.inputRemains.map(_ > 0).ifM(unwrap(maxBytes, timeout), takeUnwrapped(maxBytes))
192+
186193
/** Determines what to do next given the result of a handshake operation.
187194
* Must be called with `handshakeSem`.
188195
*/

0 commit comments

Comments
 (0)