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.net.UploadDataProvider; | |
8 import org.chromium.net.UploadDataSink; | |
9 | |
10 import java.io.IOException; | |
11 import java.io.OutputStream; | |
12 import java.nio.ByteBuffer; | |
13 | |
14 /** | |
15 * An implementation of {@link java.io.OutputStream} to send data to a server, | |
16 * when {@link CronetHttpURLConnection#setFixedLengthStreamingMode} is used. | |
17 * This implementation does not buffer entire request body in memory. | |
pauljensen
2015/03/10 17:31:06
What threads do we expect this to be called from?
xunjieli
2015/03/12 21:55:10
I guess I was assuming that writes happen on the t
| |
18 */ | |
19 final class CronetOutputStream extends OutputStream implements UploadDataProvide r { | |
20 // CronetOutputStream buffers up to this value and wait for UploadDataStream | |
21 // to consume the data. | |
22 // FIXME: confirm this number is what we want to buffer internally. | |
pauljensen
2015/03/10 17:31:06
can we either resolve this FIXME now or change it
xunjieli
2015/03/12 21:55:10
Done.
| |
23 private static int sDefaultBufferLength = 2048; | |
24 private final CronetHttpURLConnection mConnection; | |
25 private final long mContentLength; | |
26 private final ByteBuffer mBuffer; | |
27 private long mBytesReceived; | |
28 | |
29 /** | |
30 * Packaged protected constructor. | |
31 * @param connection The CronetHttpURLConnection object. | |
32 * @param contentLength The content length of the request body. Non-zero for | |
33 * non-chunked upload. | |
34 */ | |
35 CronetOutputStream(CronetHttpURLConnection connection, long contentLength) { | |
36 if (connection == null) { | |
37 throw new NullPointerException(); | |
38 } | |
39 if (contentLength < 0) { | |
40 throw new IllegalArgumentException( | |
41 "Content length must be larger than 0 for non-chunked upload ."); | |
42 } | |
43 mContentLength = contentLength; | |
44 int bufferSize = (int) Math.min(mContentLength, sDefaultBufferLength); | |
45 mBuffer = ByteBuffer.allocate(bufferSize); | |
46 mConnection = connection; | |
47 mBytesReceived = 0; | |
48 } | |
49 | |
50 @Override | |
51 public long getLength() { | |
52 return mContentLength; | |
53 } | |
54 | |
55 @Override | |
56 public void read(UploadDataSink uploadDataSink, ByteBuffer byteBuffer) { | |
57 mBuffer.flip(); | |
58 byteBuffer.put(mBuffer); | |
pauljensen
2015/03/10 17:31:06
how do we know this won't overflow? can we add a
xunjieli
2015/03/12 21:55:10
Sorry, I think there's a risk of overflowing.
Don
| |
59 // Reuse this buffer. | |
60 mBuffer.clear(); | |
61 uploadDataSink.onReadSucceeded(false); | |
62 // Wait for more data if not enough data is received. | |
63 if (mBytesReceived < mContentLength) { | |
64 mConnection.waitForPostData(); | |
65 } | |
66 } | |
67 | |
68 @Override | |
69 public void rewind(UploadDataSink uploadDataSink) { | |
70 uploadDataSink.onRewindError(null); | |
71 } | |
72 | |
73 @Override | |
74 public void write(int oneByte) throws IOException { | |
75 if (mBuffer.position() == mBuffer.limit()) { | |
76 // Wait until buffer is consumed. | |
77 mConnection.waitForPostDataConsumed(); | |
78 } | |
79 mBuffer.put((byte) oneByte); | |
80 mBytesReceived++; | |
81 if (mBytesReceived == mContentLength) { | |
82 // Entire post data has been received. Now wait for network stack to | |
83 // consume it. | |
84 mConnection.waitForPostDataConsumed(); | |
85 } | |
86 } | |
87 | |
88 @Override | |
89 public void write(byte[] buffer, int offset, int count) throws IOException { | |
90 if (buffer.length - offset < count || offset < 0 || count < 0) { | |
91 throw new IndexOutOfBoundsException(); | |
92 } | |
93 if (count == 0) { | |
94 return; | |
95 } | |
96 int toSent = count; | |
pauljensen
2015/03/10 17:31:06
how about renaming toSent to toSend
xunjieli
2015/03/12 21:55:10
Done.
| |
97 while (toSent > 0) { | |
98 if (mBuffer.position() == mBuffer.limit()) { | |
99 // Wait until buffer is consumed. | |
100 mConnection.waitForPostDataConsumed(); | |
101 } | |
102 int sent = Math.min(toSent, mBuffer.limit() - mBuffer.position()); | |
103 mBuffer.put(buffer, offset + count - toSent, sent); | |
104 toSent -= sent; | |
105 } | |
106 mBytesReceived += count; | |
107 if (mBytesReceived == mContentLength) { | |
108 // Entire post data has been received. Now wait for network stack to | |
109 // consume it. | |
110 mConnection.waitForPostDataConsumed(); | |
111 } | |
112 } | |
113 } | |
OLD | NEW |