Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(411)

Side by Side Diff: net/base/upload_data_stream.cc

Issue 6134003: Prototype of chunked transfer encoded POST. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 9 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 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 #include "net/base/upload_data_stream.h" 5 #include "net/base/upload_data_stream.h"
6 6
7 #include "base/file_util.h" 7 #include "base/file_util.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "net/base/file_stream.h" 9 #include "net/base/file_stream.h"
10 #include "net/base/io_buffer.h" 10 #include "net/base/io_buffer.h"
11 #include "net/base/net_errors.h" 11 #include "net/base/net_errors.h"
12 12
13 namespace net { 13 namespace net {
14 14
15 UploadDataStream* UploadDataStream::Create(UploadData* data, int* error_code) { 15 UploadDataStream* UploadDataStream::Create(UploadData* data, int* error_code) {
16 scoped_ptr<UploadDataStream> stream(new UploadDataStream(data)); 16 scoped_ptr<UploadDataStream> stream(new UploadDataStream(data));
17 int rv = stream->FillBuf(); 17 int rv = stream->FillBuf();
18 if (error_code) 18 if (error_code)
19 *error_code = rv; 19 *error_code = rv;
20 if (rv != OK) 20 if (rv != OK)
21 return NULL; 21 return NULL;
22 22
23 return stream.release(); 23 return stream.release();
24 } 24 }
25 25
26 UploadDataStream::UploadDataStream(UploadData* data) 26 UploadDataStream::UploadDataStream(UploadData* data)
27 : data_(data), 27 : data_(data),
28 buf_(new IOBuffer(kBufSize)), 28 buf_(new IOBuffer(kBufSize)),
29 buf_len_(0), 29 buf_len_(0),
30 next_element_(data->elements()->begin()), 30 next_element_(0),
31 next_element_offset_(0), 31 next_element_offset_(0),
32 next_element_remaining_(0), 32 next_element_remaining_(0),
33 total_size_(data->GetContentLength()), 33 total_size_(data->GetContentLength()),
34 current_position_(0), 34 current_position_(0),
35 waiting_for_data_(false),
36 ALLOW_THIS_IN_INITIALIZER_LIST(
37 upload_data_callback_(this, &UploadDataStream::OnDataAvailable)),
38 data_callback_(NULL),
35 eof_(false) { 39 eof_(false) {
40 if (data_->is_chunked()) {
41 waiting_for_data_ = true;
42 data_->set_data_callback(&upload_data_callback_);
43 }
36 } 44 }
37 45
38 UploadDataStream::~UploadDataStream() { 46 UploadDataStream::~UploadDataStream() {
39 } 47 }
40 48
41 void UploadDataStream::DidConsume(size_t num_bytes) { 49 void UploadDataStream::DidConsume(size_t num_bytes) {
42 DCHECK_LE(num_bytes, buf_len_); 50 DCHECK_LE(num_bytes, buf_len_);
43 DCHECK(!eof_); 51 DCHECK(!eof_);
44 52
45 buf_len_ -= num_bytes; 53 buf_len_ -= num_bytes;
46 if (buf_len_) 54 if (buf_len_)
47 memmove(buf_->data(), buf_->data() + num_bytes, buf_len_); 55 memmove(buf_->data(), buf_->data() + num_bytes, buf_len_);
48 56
49 FillBuf(); 57 FillBuf();
50 58
51 current_position_ += num_bytes; 59 current_position_ += num_bytes;
52 } 60 }
53 61
62 void UploadDataStream::set_data_callback(CompletionCallback* callback) {
63 DCHECK(!eof() && waiting_for_data());
64 data_callback_ = callback;
65 }
66
67 void UploadDataStream::OnDataAvailable(int result) {
68 if (!waiting_for_data_)
69 return;
70
71 waiting_for_data_ = false;
72 FillBuf();
73
74 // Callback may be NULL if we received more data before the previously
75 // received data was read.
76 if (data_callback_) {
77 CompletionCallback* c = data_callback_;
78 data_callback_ = NULL;
79 c->Run(0);
wtc 2011/01/12 02:39:02 Should you pass 'result' instead of 0 to c->Run()?
Satish 2011/01/13 17:43:27 No. A non-zero value is given only by the socket w
80 }
81 }
82
54 int UploadDataStream::FillBuf() { 83 int UploadDataStream::FillBuf() {
55 std::vector<UploadData::Element>::iterator end = 84 std::vector<UploadData::Element>& elements = *data_->elements();
56 data_->elements()->end(); 85 if (elements.size() == 0 && data_->is_chunked()) {
86 // We are waiting for data from UploadData, so nothing to do.
87 return OK;
88 }
57 89
58 while (buf_len_ < kBufSize && next_element_ != end) { 90 while (buf_len_ < kBufSize && next_element_ < elements.size()) {
59 bool advance_to_next_element = false; 91 bool advance_to_next_element = false;
60 92
61 UploadData::Element& element = *next_element_; 93 UploadData::Element& element = elements[next_element_];
62 94
63 size_t size_remaining = kBufSize - buf_len_; 95 size_t size_remaining = kBufSize - buf_len_;
64 if (element.type() == UploadData::TYPE_BYTES) { 96 if (element.type() == UploadData::TYPE_BYTES ||
97 element.type() == UploadData::TYPE_CHUNK) {
65 const std::vector<char>& d = element.bytes(); 98 const std::vector<char>& d = element.bytes();
66 size_t count = d.size() - next_element_offset_; 99 size_t count = d.size() - next_element_offset_;
67 100
68 size_t bytes_copied = std::min(count, size_remaining); 101 size_t bytes_copied = std::min(count, size_remaining);
69 102
70 memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied); 103 if (bytes_copied > 0)
104 memcpy(buf_->data() + buf_len_, &d[next_element_offset_], bytes_copied);
71 buf_len_ += bytes_copied; 105 buf_len_ += bytes_copied;
72 106
73 if (bytes_copied == count) { 107 if (bytes_copied == count) {
74 advance_to_next_element = true; 108 advance_to_next_element = true;
75 } else { 109 } else {
76 next_element_offset_ += bytes_copied; 110 next_element_offset_ += bytes_copied;
77 } 111 }
78 } else { 112 } else {
79 DCHECK(element.type() == UploadData::TYPE_FILE); 113 DCHECK(element.type() == UploadData::TYPE_FILE);
80 114
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 } 153 }
120 154
121 if (advance_to_next_element) { 155 if (advance_to_next_element) {
122 ++next_element_; 156 ++next_element_;
123 next_element_offset_ = 0; 157 next_element_offset_ = 0;
124 next_element_remaining_ = 0; 158 next_element_remaining_ = 0;
125 next_element_stream_.reset(); 159 next_element_stream_.reset();
126 } 160 }
127 } 161 }
128 162
129 if (next_element_ == end && !buf_len_) 163 if (next_element_ == elements.size() && !buf_len_) {
130 eof_ = true; 164 // If the last element in the list is a CHUNK buffer, we have to wait
165 // for more data to come in.
166 if (elements.size() > 0 &&
167 elements[elements.size() - 1].type() == UploadData::TYPE_CHUNK) {
168 waiting_for_data_ = true;
169 } else {
170 eof_ = true;
171 }
172 }
131 173
132 return OK; 174 return OK;
133 } 175 }
134 176
135 } // namespace net 177 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698