1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/net/http_body.h"
16
17 #include <string.h>
18
19 #include <algorithm>
20 #include <limits>
21
22 #include "base/logging.h"
23 #include "util/misc/implicit_cast.h"
24
25 namespace crashpad {
26
StringHTTPBodyStream(const std::string & string)27 StringHTTPBodyStream::StringHTTPBodyStream(const std::string& string)
28 : HTTPBodyStream(), string_(string), bytes_read_() {
29 }
30
~StringHTTPBodyStream()31 StringHTTPBodyStream::~StringHTTPBodyStream() {
32 }
33
GetBytesBuffer(uint8_t * buffer,size_t max_len)34 FileOperationResult StringHTTPBodyStream::GetBytesBuffer(uint8_t* buffer,
35 size_t max_len) {
36 size_t num_bytes_remaining = string_.length() - bytes_read_;
37 if (num_bytes_remaining == 0) {
38 return num_bytes_remaining;
39 }
40
41 size_t num_bytes_returned = std::min(
42 std::min(num_bytes_remaining, max_len),
43 implicit_cast<size_t>(std::numeric_limits<FileOperationResult>::max()));
44 memcpy(buffer, &string_[bytes_read_], num_bytes_returned);
45 bytes_read_ += num_bytes_returned;
46 return num_bytes_returned;
47 }
48
FileReaderHTTPBodyStream(FileReaderInterface * reader)49 FileReaderHTTPBodyStream::FileReaderHTTPBodyStream(FileReaderInterface* reader)
50 : HTTPBodyStream(), reader_(reader), reached_eof_(false) {
51 DCHECK(reader_);
52 }
53
~FileReaderHTTPBodyStream()54 FileReaderHTTPBodyStream::~FileReaderHTTPBodyStream() {}
55
GetBytesBuffer(uint8_t * buffer,size_t max_len)56 FileOperationResult FileReaderHTTPBodyStream::GetBytesBuffer(uint8_t* buffer,
57 size_t max_len) {
58 if (reached_eof_) {
59 return 0;
60 }
61
62 FileOperationResult rv = reader_->Read(buffer, max_len);
63 if (rv == 0) {
64 reached_eof_ = true;
65 }
66 return rv;
67 }
68
CompositeHTTPBodyStream(const CompositeHTTPBodyStream::PartsList & parts)69 CompositeHTTPBodyStream::CompositeHTTPBodyStream(
70 const CompositeHTTPBodyStream::PartsList& parts)
71 : HTTPBodyStream(), parts_(parts), current_part_(parts_.begin()) {
72 }
73
~CompositeHTTPBodyStream()74 CompositeHTTPBodyStream::~CompositeHTTPBodyStream() {
75 for (auto& item : parts_)
76 delete item;
77 }
78
GetBytesBuffer(uint8_t * buffer,size_t buffer_len)79 FileOperationResult CompositeHTTPBodyStream::GetBytesBuffer(uint8_t* buffer,
80 size_t buffer_len) {
81 FileOperationResult max_len = std::min(
82 buffer_len,
83 implicit_cast<size_t>(std::numeric_limits<FileOperationResult>::max()));
84 FileOperationResult bytes_copied = 0;
85 while (bytes_copied < max_len && current_part_ != parts_.end()) {
86 FileOperationResult this_read =
87 (*current_part_)
88 ->GetBytesBuffer(buffer + bytes_copied, max_len - bytes_copied);
89
90 if (this_read == 0) {
91 // If the current part has returned 0 indicating EOF, advance the current
92 // part and try again.
93 ++current_part_;
94 } else if (this_read < 0) {
95 return this_read;
96 }
97 bytes_copied += this_read;
98 }
99
100 return bytes_copied;
101 }
102
103 } // namespace crashpad
104