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