Skip to content

Commit 9e25e03

Browse files
authored
Get Socket.inputStream and outputStream eagerly (#1669)
I was looking into migrating OkHttp to use Okio's Socket internally and I came across a small behavior change - previously we were getting the stream once and reusing it on each call, but now Okio is getting the stream on each access. With this change the Socket.asOkioSocket() API behaves more consistently with Socket.source() and Socket.sink(). Co-authored-by: Jesse Wilson <jwilson@squareup.com>
1 parent 0e48b0d commit 9e25e03

2 files changed

Lines changed: 25 additions & 4 deletions

File tree

okio/src/jvmMain/kotlin/okio/internal/DefaultSocket.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
4848
override fun toString() = socket.toString()
4949

5050
inner class SocketSink : Sink {
51+
private val outputStream = socket.outputStream
5152
private val timeout = SocketAsyncTimeout(socket)
5253

5354
override fun write(source: Buffer, byteCount: Long) {
@@ -58,7 +59,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
5859
val head = source.head!!
5960
val toCopy = minOf(remaining, head.limit - head.pos).toInt()
6061
timeout.withTimeout {
61-
socket.outputStream.write(head.data, head.pos, toCopy)
62+
outputStream.write(head.data, head.pos, toCopy)
6263
}
6364

6465
head.pos += toCopy
@@ -74,7 +75,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
7475

7576
override fun flush() {
7677
timeout.withTimeout {
77-
socket.outputStream.flush()
78+
outputStream.flush()
7879
}
7980
}
8081

@@ -90,7 +91,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
9091
// Close this stream only.
9192
else -> {
9293
if (socket.isClosed || socket.isOutputShutdown) return // Nothing to do.
93-
socket.outputStream.flush()
94+
outputStream.flush()
9495
socket.shutdownOutput()
9596
}
9697
}
@@ -103,6 +104,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
103104
}
104105

105106
inner class SocketSource : Source {
107+
private val inputStream = socket.inputStream
106108
private val timeout = SocketAsyncTimeout(socket)
107109

108110
override fun read(sink: Buffer, byteCount: Long): Long {
@@ -113,7 +115,7 @@ internal class DefaultSocket(val socket: JavaNetSocket) : Socket {
113115
val maxToCopy = minOf(byteCount, Segment.Companion.SIZE - tail.limit).toInt()
114116
val bytesRead = try {
115117
timeout.withTimeout {
116-
socket.inputStream.read(tail.data, tail.limit, maxToCopy)
118+
inputStream.read(tail.data, tail.limit, maxToCopy)
117119
}
118120
} catch (e: AssertionError) {
119121
if (e.isAndroidGetsocknameError) throw IOException(e)

okio/src/jvmTest/kotlin/okio/SocketTest.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import java.io.InterruptedIOException
2525
import java.net.InetAddress
2626
import java.net.InetSocketAddress
2727
import java.net.ServerSocket
28+
import java.net.SocketException
2829
import java.util.concurrent.CompletableFuture
2930
import java.util.concurrent.TimeUnit
3031
import javax.net.SocketFactory
@@ -253,6 +254,24 @@ class SocketTest(val factory: Factory = Factory.Default) {
253254
assertThat(javaNetSocket.isClosed).isFalse()
254255
}
255256

257+
@Test
258+
fun cannotCreateOkioSocketFromClosedJavaNetSocket() {
259+
val javaNetSocket = (this.socket as? DefaultSocket)?.socket ?: return
260+
javaNetSocket.close()
261+
262+
assertFailsWith<SocketException> {
263+
javaNetSocket.asOkioSocket()
264+
}
265+
}
266+
267+
@Test
268+
fun cannotCreateOkioSocketFromUnconnectedJavaNetSocket() {
269+
val unconnected = SocketFactory.getDefault().createSocket()
270+
assertFailsWith<SocketException> {
271+
unconnected.asOkioSocket()
272+
}
273+
}
274+
256275
@Suppress("ktlint:trailing-comma-on-declaration-site")
257276
enum class Factory {
258277
/** Implements an okio.Socket using the `java.net.Socket` API on OS sockets. */

0 commit comments

Comments
 (0)