Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.net.urlconnection; | 5 package org.chromium.net.urlconnection; |
| 6 | 6 |
| 7 import org.chromium.base.VisibleForTesting; | 7 import org.chromium.base.VisibleForTesting; |
| 8 import org.chromium.net.UploadDataProvider; | 8 import org.chromium.net.UploadDataProvider; |
| 9 import org.chromium.net.UploadDataSink; | 9 import org.chromium.net.UploadDataSink; |
| 10 | 10 |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 final class CronetFixedModeOutputStream extends CronetOutputStream { | 23 final class CronetFixedModeOutputStream extends CronetOutputStream { |
| 24 // CronetFixedModeOutputStream buffers up to this value and wait for UploadD ataStream | 24 // CronetFixedModeOutputStream buffers up to this value and wait for UploadD ataStream |
| 25 // to consume the data. This field is non-final, so it can be changed for te sts. | 25 // to consume the data. This field is non-final, so it can be changed for te sts. |
| 26 // Using 16384 bytes is because the internal read buffer is 14520 for QUIC, | 26 // Using 16384 bytes is because the internal read buffer is 14520 for QUIC, |
| 27 // 16384 for SPDY, and 16384 for normal HTTP/1.1 stream. | 27 // 16384 for SPDY, and 16384 for normal HTTP/1.1 stream. |
| 28 @VisibleForTesting | 28 @VisibleForTesting |
| 29 private static int sDefaultBufferLength = 16384; | 29 private static int sDefaultBufferLength = 16384; |
| 30 private final CronetHttpURLConnection mConnection; | 30 private final CronetHttpURLConnection mConnection; |
| 31 private final MessageLoop mMessageLoop; | 31 private final MessageLoop mMessageLoop; |
| 32 private final long mContentLength; | 32 private final long mContentLength; |
| 33 // Internal buffer for storing the bytes written by consumer and for providi ng | |
|
pauljensen
2016/06/10 17:45:44
"written" has several possible meanings here (e.g.
xunjieli
2016/06/10 18:48:12
Done.
| |
| 34 // bytes for the native stack to consume in UploadDataProvider.read(). | |
|
pauljensen
2016/06/10 17:45:44
the consuming isn't really done in UploadDataProvi
xunjieli
2016/06/10 18:48:12
Done.
| |
| 35 // CronetFixedModeOutputStream allows consumer to write up to sDefaultBuffer Length, | |
|
pauljensen
2016/06/10 17:45:44
consumer->the client
pauljensen
2016/06/10 17:45:45
sDefaultBufferLength->sDefaultBufferLength bytes
pauljensen
2016/06/10 17:45:45
write->provide
xunjieli
2016/06/10 18:48:12
Done.
xunjieli
2016/06/10 18:48:12
Done.
xunjieli
2016/06/10 18:48:13
Done.
| |
| 36 // and wait for UploadDataProvider.read() to be called so mBuffer is cleared | |
|
pauljensen
2016/06/10 17:45:44
so->, after which point
xunjieli
2016/06/10 18:48:11
Done.
| |
| 37 // for next round of writing. During writing, the buffer's position points | |
|
pauljensen
2016/06/10 17:45:44
for next round of writing->so the client can fill
pauljensen
2016/06/10 17:45:44
During writing->While the client is filling the bu
xunjieli
2016/06/10 18:48:11
Done.
xunjieli
2016/06/10 18:48:12
Done.
| |
| 38 // to the next byte to be written, and limit is the index at which no byte | |
|
pauljensen
2016/06/10 17:45:44
"is the index..."->"points to the end of the buffe
pauljensen
2016/06/10 17:45:44
written->provided by the client
xunjieli
2016/06/10 18:48:12
Done.
| |
| 39 // should be written. The buffer is flipped before it is passed to the | |
| 40 // UploadDataProvider for consuming. Once it is flipped, buffer position | |
| 41 // points to the next byte to be read, and limit is the index at which no | |
|
pauljensen
2016/06/10 17:45:44
read->copied to the UploadDataSink
pauljensen
2016/06/10 17:45:44
"is the index..."->"points to the end of the data
xunjieli
2016/06/10 18:48:11
Done.
xunjieli
2016/06/10 18:48:12
Done.
| |
| 42 // byte should be read. When the UploadDataProvider is done reading from | |
|
pauljensen
2016/06/10 17:45:44
"is done..."->"has provided all remaining bytes fr
xunjieli
2016/06/10 18:48:11
Done.
| |
| 43 // mBuffer, it clears mBuffer for next round of writing. | |
| 33 private final ByteBuffer mBuffer; | 44 private final ByteBuffer mBuffer; |
| 34 private final UploadDataProvider mUploadDataProvider = new UploadDataProvide rImpl(); | 45 private final UploadDataProvider mUploadDataProvider = new UploadDataProvide rImpl(); |
| 35 private long mBytesWritten; | 46 private long mBytesWritten; |
| 36 | 47 |
| 37 /** | 48 /** |
| 38 * Package protected constructor. | 49 * Package protected constructor. |
| 39 * @param connection The CronetHttpURLConnection object. | 50 * @param connection The CronetHttpURLConnection object. |
| 40 * @param contentLength The content length of the request body. Non-zero for | 51 * @param contentLength The content length of the request body. Non-zero for |
| 41 * non-chunked upload. | 52 * non-chunked upload. |
| 42 */ | 53 */ |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 53 int bufferSize = (int) Math.min(mContentLength, sDefaultBufferLength); | 64 int bufferSize = (int) Math.min(mContentLength, sDefaultBufferLength); |
| 54 mBuffer = ByteBuffer.allocate(bufferSize); | 65 mBuffer = ByteBuffer.allocate(bufferSize); |
| 55 mConnection = connection; | 66 mConnection = connection; |
| 56 mMessageLoop = messageLoop; | 67 mMessageLoop = messageLoop; |
| 57 mBytesWritten = 0; | 68 mBytesWritten = 0; |
| 58 } | 69 } |
| 59 | 70 |
| 60 @Override | 71 @Override |
| 61 public void write(int oneByte) throws IOException { | 72 public void write(int oneByte) throws IOException { |
| 62 checkNotExceedContentLength(1); | 73 checkNotExceedContentLength(1); |
| 63 while (mBuffer.position() == mBuffer.limit()) { | 74 ensureBufferHasRemaining(); |
| 64 // Wait until buffer is consumed. | |
| 65 mMessageLoop.loop(); | |
| 66 } | |
| 67 mBuffer.put((byte) oneByte); | 75 mBuffer.put((byte) oneByte); |
| 68 mBytesWritten++; | 76 mBytesWritten++; |
| 69 if (mBytesWritten == mContentLength) { | 77 uploadIfComplete(); |
| 70 // Entire post data has been received. Now wait for network stack to | |
| 71 // read it. | |
| 72 mMessageLoop.loop(); | |
| 73 } | |
| 74 } | 78 } |
| 75 | 79 |
| 76 @Override | 80 @Override |
| 77 public void write(byte[] buffer, int offset, int count) throws IOException { | 81 public void write(byte[] buffer, int offset, int count) throws IOException { |
| 78 if (buffer.length - offset < count || offset < 0 || count < 0) { | 82 if (buffer.length - offset < count || offset < 0 || count < 0) { |
| 79 throw new IndexOutOfBoundsException(); | 83 throw new IndexOutOfBoundsException(); |
| 80 } | 84 } |
| 81 checkNotExceedContentLength(count); | 85 checkNotExceedContentLength(count); |
| 82 if (count == 0) { | |
| 83 return; | |
| 84 } | |
| 85 int toSend = count; | 86 int toSend = count; |
| 86 while (toSend > 0) { | 87 while (toSend > 0) { |
| 87 if (mBuffer.position() == mBuffer.limit()) { | 88 ensureBufferHasRemaining(); |
| 88 // Wait until buffer is consumed. | 89 int sent = Math.min(toSend, mBuffer.remaining()); |
| 89 mMessageLoop.loop(); | |
| 90 } | |
| 91 int sent = Math.min(toSend, mBuffer.limit() - mBuffer.position()); | |
| 92 mBuffer.put(buffer, offset + count - toSend, sent); | 90 mBuffer.put(buffer, offset + count - toSend, sent); |
| 93 toSend -= sent; | 91 toSend -= sent; |
| 94 } | 92 } |
| 95 mBytesWritten += count; | 93 mBytesWritten += count; |
| 94 uploadIfComplete(); | |
| 95 } | |
| 96 | |
| 97 /** | |
| 98 * If {@code mBuffer} is full, wait until it is consumed and there is | |
| 99 * space to write more data to it. | |
| 100 */ | |
| 101 private void ensureBufferHasRemaining() { | |
| 102 if (!mBuffer.hasRemaining()) { | |
| 103 uploadBufferInternal(); | |
| 104 } | |
| 105 } | |
| 106 | |
| 107 /** | |
| 108 * Waits the native stack to upload data since all bytes have been written. | |
|
pauljensen
2016/06/10 17:45:44
data->mBuffer's contents
pauljensen
2016/06/10 17:45:44
since...->because the client has provided all byte
pauljensen
2016/06/10 17:45:44
the->for the
xunjieli
2016/06/10 18:48:12
Done.
xunjieli
2016/06/10 18:48:12
Done.
xunjieli
2016/06/10 18:48:12
Done.
| |
| 109 */ | |
| 110 private void uploadIfComplete() { | |
| 96 if (mBytesWritten == mContentLength) { | 111 if (mBytesWritten == mContentLength) { |
| 97 // Entire post data has been received. Now wait for network stack to | 112 // Entire post data has been received. Now wait for network stack to |
| 98 // read it. | 113 // read it. |
| 99 mMessageLoop.loop(); | 114 uploadBufferInternal(); |
| 100 } | 115 } |
| 101 } | 116 } |
| 102 | 117 |
| 103 /** | 118 /** |
| 119 * Helper function to upload the buffer to the native stack. This function | |
|
pauljensen
2016/06/10 17:45:44
buffer->{@code mBuffer}
xunjieli
2016/06/10 18:48:12
Done.
| |
| 120 * blocks until {@code mBuffer} is consumed and there is space to write more | |
| 121 * data. | |
| 122 */ | |
| 123 private void uploadBufferInternal() { | |
| 124 mBuffer.flip(); | |
| 125 mMessageLoop.loop(); | |
| 126 } | |
| 127 | |
| 128 /** | |
| 104 * Throws {@link java.net.ProtocolException} if adding {@code numBytes} will | 129 * Throws {@link java.net.ProtocolException} if adding {@code numBytes} will |
| 105 * exceed content length. | 130 * exceed content length. |
| 106 */ | 131 */ |
| 107 private void checkNotExceedContentLength(int numBytes) throws ProtocolExcept ion { | 132 private void checkNotExceedContentLength(int numBytes) throws ProtocolExcept ion { |
| 108 if (mBytesWritten + numBytes > mContentLength) { | 133 if (mBytesWritten + numBytes > mContentLength) { |
| 109 throw new ProtocolException("expected " | 134 throw new ProtocolException("expected " |
| 110 + (mContentLength - mBytesWritten) + " bytes but received " | 135 + (mContentLength - mBytesWritten) + " bytes but received " |
| 111 + numBytes); | 136 + numBytes); |
| 112 } | 137 } |
| 113 } | 138 } |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 134 } | 159 } |
| 135 | 160 |
| 136 private class UploadDataProviderImpl extends UploadDataProvider { | 161 private class UploadDataProviderImpl extends UploadDataProvider { |
| 137 @Override | 162 @Override |
| 138 public long getLength() { | 163 public long getLength() { |
| 139 return mContentLength; | 164 return mContentLength; |
| 140 } | 165 } |
| 141 | 166 |
| 142 @Override | 167 @Override |
| 143 public void read(final UploadDataSink uploadDataSink, final ByteBuffer b yteBuffer) { | 168 public void read(final UploadDataSink uploadDataSink, final ByteBuffer b yteBuffer) { |
| 144 final int availableSpace = byteBuffer.remaining(); | 169 if (byteBuffer.remaining() >= mBuffer.remaining()) { |
| 145 if (availableSpace < mBuffer.position()) { | |
| 146 // byteBuffer does not have enough capacity, so only put a porti on | |
| 147 // of mBuffer in it. | |
| 148 byteBuffer.put(mBuffer.array(), 0, availableSpace); | |
| 149 mBuffer.position(availableSpace); | |
| 150 // Move remaining buffer to the head of the buffer for use in th e | |
| 151 // next read call. | |
| 152 mBuffer.compact(); | |
| 153 } else { | |
| 154 // byteBuffer has enough capacity to hold the content of mBuffer . | |
| 155 mBuffer.flip(); | |
| 156 byteBuffer.put(mBuffer); | 170 byteBuffer.put(mBuffer); |
| 157 // Reuse this buffer. | 171 // Reuse this buffer. |
| 158 mBuffer.clear(); | 172 mBuffer.clear(); |
| 173 uploadDataSink.onReadSucceeded(false); | |
| 159 // Quit message loop so embedder can write more data. | 174 // Quit message loop so embedder can write more data. |
| 160 mMessageLoop.quit(); | 175 mMessageLoop.quit(); |
| 176 } else { | |
| 177 mBuffer.position(mBuffer.position() + byteBuffer.remaining()); | |
| 178 byteBuffer.put(mBuffer.array(), mBuffer.position() - byteBuffer. remaining(), | |
| 179 byteBuffer.remaining()); | |
| 180 uploadDataSink.onReadSucceeded(false); | |
| 161 } | 181 } |
| 162 uploadDataSink.onReadSucceeded(false); | |
| 163 } | 182 } |
| 164 | 183 |
| 165 @Override | 184 @Override |
| 166 public void rewind(UploadDataSink uploadDataSink) { | 185 public void rewind(UploadDataSink uploadDataSink) { |
| 167 uploadDataSink.onRewindError( | 186 uploadDataSink.onRewindError( |
| 168 new HttpRetryException("Cannot retry streamed Http body", -1 )); | 187 new HttpRetryException("Cannot retry streamed Http body", -1 )); |
| 169 } | 188 } |
| 170 } | 189 } |
| 171 | 190 |
| 172 /** | 191 /** |
| 173 * Sets the default buffer length for use in tests. | 192 * Sets the default buffer length for use in tests. |
| 174 */ | 193 */ |
| 175 @VisibleForTesting | 194 @VisibleForTesting |
| 176 static void setDefaultBufferLengthForTesting(int length) { | 195 static void setDefaultBufferLengthForTesting(int length) { |
| 177 sDefaultBufferLength = length; | 196 sDefaultBufferLength = length; |
| 178 } | 197 } |
| 179 } | 198 } |
| OLD | NEW |