Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.net.urlconnection; | |
| 6 | |
| 7 import org.chromium.base.VisibleForTesting; | |
| 8 import org.chromium.net.UploadDataProvider; | |
| 9 import org.chromium.net.UploadDataSink; | |
| 10 | |
| 11 import java.io.IOException; | |
| 12 import java.io.OutputStream; | |
| 13 import java.nio.ByteBuffer; | |
| 14 | |
| 15 /** | |
| 16 * An implementation of {@link java.io.OutputStream} to send data to a server, | |
| 17 * when {@link CronetHttpURLConnection#setFixedLengthStreamingMode} is used. | |
| 18 * This implementation does not buffer the entire request body in memory. | |
| 19 * Note that {@link #write} should only be called from the thread on which the | |
| 20 * {@link #mConnection} is created. | |
| 21 */ | |
| 22 final class CronetOutputStream extends OutputStream implements UploadDataProvide r { | |
| 23 // CronetOutputStream buffers up to this value and wait for UploadDataStream | |
| 24 // to consume the data. This field is non-final, so it can be changed for te sts. | |
| 25 // TODO(xunjieli): figure out whether this default value should be changed. | |
| 26 @VisibleForTesting | |
|
mmenke
2015/03/13 14:51:12
What does this do? I don't see any of our tests u
xunjieli
2015/03/13 19:26:40
The docs on this flag says "Annotation used to mar
| |
| 27 private static int sDefaultBufferLength = 2048; | |
|
mmenke
2015/03/13 14:51:12
This should probably be 32k
xunjieli
2015/03/13 19:26:40
But 32k is larger than all the read buffers used i
mmenke
2015/03/25 18:34:57
You're right. We generally read from URLRequests
| |
| 28 private final CronetHttpURLConnection mConnection; | |
| 29 private final long mContentLength; | |
| 30 private final ByteBuffer mBuffer; | |
| 31 private long mBytesReceived; | |
| 32 | |
| 33 /** | |
| 34 * Packaged protected constructor. | |
| 35 * @param connection The CronetHttpURLConnection object. | |
| 36 * @param contentLength The content length of the request body. Non-zero for | |
| 37 * non-chunked upload. | |
| 38 */ | |
| 39 CronetOutputStream(CronetHttpURLConnection connection, long contentLength) { | |
| 40 if (connection == null) { | |
| 41 throw new NullPointerException(); | |
| 42 } | |
| 43 if (contentLength < 0) { | |
| 44 throw new IllegalArgumentException( | |
| 45 "Content length must be larger than 0 for non-chunked upload ."); | |
| 46 } | |
| 47 mContentLength = contentLength; | |
| 48 int bufferSize = (int) Math.min(mContentLength, sDefaultBufferLength); | |
| 49 mBuffer = ByteBuffer.allocate(bufferSize); | |
| 50 mConnection = connection; | |
| 51 mBytesReceived = 0; | |
| 52 } | |
| 53 | |
| 54 @Override | |
| 55 public void write(int oneByte) throws IOException { | |
| 56 while (mBuffer.position() == mBuffer.limit()) { | |
| 57 // Wait until buffer is consumed. | |
| 58 mConnection.waitForRead(); | |
| 59 } | |
| 60 mBuffer.put((byte) oneByte); | |
| 61 mBytesReceived++; | |
| 62 if (mBytesReceived == mContentLength) { | |
| 63 // Entire post data has been received. Now wait for network stack to | |
| 64 // read it. | |
| 65 mConnection.waitForRead(); | |
| 66 } | |
| 67 } | |
| 68 | |
| 69 @Override | |
| 70 public void write(byte[] buffer, int offset, int count) throws IOException { | |
| 71 if (buffer.length - offset < count || offset < 0 || count < 0) { | |
| 72 throw new IndexOutOfBoundsException(); | |
| 73 } | |
| 74 if (count == 0) { | |
| 75 return; | |
| 76 } | |
| 77 int toSend = count; | |
| 78 while (toSend > 0) { | |
| 79 if (mBuffer.position() == mBuffer.limit()) { | |
| 80 // Wait until buffer is consumed. | |
| 81 mConnection.waitForRead(); | |
| 82 } | |
| 83 int sent = Math.min(toSend, mBuffer.limit() - mBuffer.position()); | |
| 84 mBuffer.put(buffer, offset + count - toSend, sent); | |
| 85 toSend -= sent; | |
| 86 } | |
| 87 mBytesReceived += count; | |
| 88 if (mBytesReceived == mContentLength) { | |
| 89 // Entire post data has been received. Now wait for network stack to | |
| 90 // read it. | |
| 91 mConnection.waitForRead(); | |
| 92 } | |
| 93 } | |
| 94 | |
| 95 // Below are UploadDataProvider implementations. Only intended to be used | |
| 96 // within Cronet. | |
| 97 | |
| 98 @Override | |
| 99 public long getLength() { | |
| 100 return mContentLength; | |
| 101 } | |
| 102 | |
| 103 @Override | |
| 104 public void read(final UploadDataSink uploadDataSink, final ByteBuffer byteB uffer) { | |
| 105 Runnable readTask = new Runnable() { | |
| 106 @Override | |
| 107 public void run() { | |
| 108 if (byteBuffer.remaining() < mBuffer.position()) { | |
| 109 // byteBuffer does not have enough capacity, so only put a p ortion | |
| 110 // of mBuffer in it. | |
| 111 mBuffer.position(byteBuffer.remaining()); | |
| 112 byteBuffer.put(mBuffer.array(), 0, byteBuffer.remaining()); | |
| 113 // Move remaining buffer to the head of the buffer for use i n the | |
| 114 // next read call. | |
| 115 mBuffer.compact(); | |
| 116 uploadDataSink.onReadSucceeded(false); | |
| 117 } else { | |
| 118 // byteBuffer has enough capacity to hold content in mBuffer . | |
| 119 mBuffer.flip(); | |
| 120 byteBuffer.put(mBuffer); | |
| 121 // Reuse this buffer. | |
| 122 mBuffer.clear(); | |
| 123 uploadDataSink.onReadSucceeded(false); | |
| 124 } | |
| 125 } | |
| 126 }; | |
| 127 if (mBuffer.position() == 0) { | |
| 128 // Exit the message loop, so consumer can write more data. | |
| 129 if (mBytesReceived < mContentLength) { | |
| 130 mConnection.postponeRead(readTask); | |
| 131 } | |
| 132 } else { | |
| 133 readTask.run(); | |
| 134 } | |
| 135 } | |
| 136 | |
| 137 @Override | |
| 138 public void rewind(UploadDataSink uploadDataSink) { | |
| 139 uploadDataSink.onRewindError(null); | |
| 140 } | |
| 141 | |
| 142 /** | |
| 143 * Sets the default buffer length for use in tests. | |
| 144 */ | |
| 145 @VisibleForTesting | |
| 146 static void setDefaultBufferLengthForTesting(int length) { | |
| 147 sDefaultBufferLength = length; | |
| 148 } | |
| 149 } | |
| OLD | NEW |