2323import com .google .common .collect .ImmutableList ;
2424import com .google .common .collect .ImmutableMap ;
2525import com .google .common .io .BaseEncoding ;
26- import com .google .common .io .ByteStreams ;
2726import com .google .protobuf .ByteString ;
2827import com .google .protobuf .Struct ;
29- import com .google .protobuf .UnsafeByteOperations ;
3028import com .google .protobuf .Value ;
3129import io .envoyproxy .envoy .config .core .v3 .HeaderMap ;
3230import io .envoyproxy .envoy .extensions .filters .http .ext_proc .v3 .ProcessingMode ;
4947import io .grpc .ClientInterceptor ;
5048import io .grpc .Context ;
5149import io .grpc .Deadline ;
52- import io .grpc .Detachable ;
5350import io .grpc .DoubleHistogramMetricInstrument ;
5451import io .grpc .Drainable ;
5552import io .grpc .ForwardingClientCall .SimpleForwardingClientCall ;
5653import io .grpc .ForwardingClientCallListener .SimpleForwardingClientCallListener ;
57- import io .grpc .HasByteBuffer ;
5854import io .grpc .KnownLength ;
5955import io .grpc .Metadata ;
6056import io .grpc .MethodDescriptor ;
8177import java .io .IOException ;
8278import java .io .InputStream ;
8379import java .io .OutputStream ;
84- import java .nio .ByteBuffer ;
8580import java .util .ArrayList ;
8681import java .util .List ;
8782import java .util .Locale ;
@@ -1325,13 +1320,16 @@ public void onMessage(InputStream message) {
13251320 }
13261321
13271322 try {
1328- ByteString bodyByteString = inboundStreamToByteString (message );
1323+ ByteString bodyByteString = ByteString . readFrom (message );
13291324 sendResponseBodyToExtProc (bodyByteString , false );
13301325 dataPlaneClientCall .bodyMessageSentToExtProc .set (true );
13311326
13321327 if (dataPlaneClientCall .getConfig ().getObservabilityMode ()) {
1328+ // If needed, downstream reading can be made more optimal by creating a wrapped
1329+ // Inputstream wraps the underlying bytestring and that implements HasByteBuffer,
1330+ // Detachable, KnownLength
13331331 dataPlaneClientCall .getCallContext ().run (
1334- () -> delegate ().onMessage (new InboundZeroCopyInputStream ( bodyByteString )));
1332+ () -> delegate ().onMessage (bodyByteString . newInput ( )));
13351333 }
13361334 } catch (IOException e ) {
13371335 rawCall .cancel ("Failed to read server response" , e );
@@ -1443,8 +1441,11 @@ private void proceedWithClose(Status status, Metadata trailers) {
14431441 }
14441442
14451443 void onExternalBody (ByteString body ) {
1444+ // If needed, downstream reading can be made more optimal by creating a wrapped
1445+ // Inputstream wraps the underlying bytestring and that implements HasByteBuffer,
1446+ // Detachable, KnownLength
14461447 dataPlaneClientCall .getCallContext ().run (
1447- () -> delegate ().onMessage (new InboundZeroCopyInputStream ( body )));
1448+ () -> delegate ().onMessage (body . newInput ( )));
14481449 }
14491450
14501451 void unblockAfterStreamComplete () {
@@ -1537,39 +1538,6 @@ private void sendResponseBodyToExtProc(
15371538 }
15381539 }
15391540
1540- @ com .google .common .annotations .VisibleForTesting
1541- static ByteString inboundStreamToByteString (InputStream message ) throws IOException {
1542- if (message == null ) {
1543- return ByteString .EMPTY ;
1544- }
1545- if (message instanceof HasByteBuffer && ((HasByteBuffer ) message ).byteBufferSupported ()) {
1546- HasByteBuffer hasByteBuffer = (HasByteBuffer ) message ;
1547- List <ByteString > chunks = new ArrayList <>();
1548- while (message .available () > 0 ) {
1549- ByteBuffer byteBuffer = hasByteBuffer .getByteBuffer ();
1550- if (byteBuffer != null && byteBuffer .hasRemaining ()) {
1551- int remaining = byteBuffer .remaining ();
1552- chunks .add (UnsafeByteOperations .unsafeWrap (byteBuffer ));
1553- long skipped = message .skip (remaining );
1554- if (skipped < remaining ) {
1555- throw new IOException ("Failed to skip all bytes in HasByteBuffer stream" );
1556- }
1557- } else {
1558- // Force advance past any exhausted component buffers at the head of the composite queue.
1559- message .skip (0 );
1560- ByteBuffer nextBuffer = hasByteBuffer .getByteBuffer ();
1561- if (nextBuffer == null || !nextBuffer .hasRemaining ()) {
1562- break ;
1563- }
1564- }
1565- }
1566- if (!chunks .isEmpty () && message .available () == 0 ) {
1567- return ByteString .copyFrom (chunks );
1568- }
1569- }
1570- byte [] bodyBytes = ByteStreams .toByteArray (message );
1571- return ByteString .copyFrom (bodyBytes );
1572- }
15731541
15741542
15751543 private static ByteString outboundStreamToByteString (InputStream message ) throws IOException {
@@ -1583,77 +1551,7 @@ private static ByteString outboundStreamToByteString(InputStream message) throws
15831551 ((Drainable ) message ).drainTo (output );
15841552 return output .toByteString ();
15851553 }
1586- byte [] bodyBytes = ByteStreams .toByteArray (message );
1587- return ByteString .copyFrom (bodyBytes );
1588- }
1589-
1590- private static final class InboundZeroCopyInputStream extends InputStream
1591- implements HasByteBuffer , Detachable , KnownLength {
1592- private final ByteString byteString ;
1593- private final InputStream delegate ;
1594- private boolean detached = false ;
1595-
1596- InboundZeroCopyInputStream (ByteString byteString ) {
1597- this .byteString = byteString ;
1598- this .delegate = byteString .newInput ();
1599- }
1600-
1601- @ Override
1602- public int read () throws IOException {
1603- return delegate .read ();
1604- }
1605-
1606- @ Override
1607- public int read (byte [] b , int off , int len ) throws IOException {
1608- return delegate .read (b , off , len );
1609- }
1610-
1611- @ Override
1612- public int available () throws IOException {
1613- return delegate .available ();
1614- }
1615-
1616- @ Override
1617- public void close () throws IOException {
1618- delegate .close ();
1619- }
1620-
1621- @ Override
1622- public boolean markSupported () {
1623- return delegate .markSupported ();
1624- }
1625-
1626- @ Override
1627- public void mark (int readlimit ) {
1628- delegate .mark (readlimit );
1629- }
1630-
1631- @ Override
1632- public void reset () throws IOException {
1633- delegate .reset ();
1634- }
1635-
1636- @ Override
1637- public boolean byteBufferSupported () {
1638- return !detached ;
1639- }
1640-
1641- @ Override
1642- public ByteBuffer getByteBuffer () {
1643- if (detached ) {
1644- throw new IllegalStateException ("Stream has been detached" );
1645- }
1646- return byteString .asReadOnlyByteBuffer ();
1647- }
1648-
1649- @ Override
1650- public InputStream detach () {
1651- if (detached ) {
1652- throw new IllegalStateException ("Stream already detached" );
1653- }
1654- detached = true ;
1655- return delegate ;
1656- }
1554+ return ByteString .readFrom (message );
16571555 }
16581556
16591557 private static final class OutboundZeroCopyInputStream extends InputStream
0 commit comments