diff options
Diffstat (limited to 'chromium/third_party/webrtc/base/multipart.cc')
-rw-r--r-- | chromium/third_party/webrtc/base/multipart.cc | 253 |
1 files changed, 253 insertions, 0 deletions
diff --git a/chromium/third_party/webrtc/base/multipart.cc b/chromium/third_party/webrtc/base/multipart.cc new file mode 100644 index 00000000000..0d73880e46f --- /dev/null +++ b/chromium/third_party/webrtc/base/multipart.cc @@ -0,0 +1,253 @@ +/* + * Copyright 2004 The WebRTC Project Authors. All rights reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + + +#include "webrtc/base/common.h" +#include "webrtc/base/httpcommon.h" +#include "webrtc/base/multipart.h" + +namespace rtc { + +/////////////////////////////////////////////////////////////////////////////// +// MultipartStream +/////////////////////////////////////////////////////////////////////////////// + +MultipartStream::MultipartStream(const std::string& type, + const std::string& boundary) + : type_(type), + boundary_(boundary), + adding_(true), + current_(0), + position_(0) { + // The content type should be multipart/*. + ASSERT(0 == strncmp(type_.c_str(), "multipart/", 10)); +} + +MultipartStream::~MultipartStream() { + Close(); +} + +void MultipartStream::GetContentType(std::string* content_type) { + ASSERT(NULL != content_type); + content_type->assign(type_); + content_type->append("; boundary="); + content_type->append(boundary_); +} + +bool MultipartStream::AddPart(StreamInterface* data_stream, + const std::string& content_disposition, + const std::string& content_type) { + if (!AddPart("", content_disposition, content_type)) + return false; + parts_.push_back(data_stream); + data_stream->SignalEvent.connect(this, &MultipartStream::OnEvent); + return true; +} + +bool MultipartStream::AddPart(const std::string& data, + const std::string& content_disposition, + const std::string& content_type) { + ASSERT(adding_); + if (!adding_) + return false; + std::stringstream ss; + if (!parts_.empty()) { + ss << "\r\n"; + } + ss << "--" << boundary_ << "\r\n"; + if (!content_disposition.empty()) { + ss << ToString(HH_CONTENT_DISPOSITION) << ": " + << content_disposition << "\r\n"; + } + if (!content_type.empty()) { + ss << ToString(HH_CONTENT_TYPE) << ": " + << content_type << "\r\n"; + } + ss << "\r\n" << data; + parts_.push_back(new MemoryStream(ss.str().data(), ss.str().size())); + return true; +} + +void MultipartStream::EndParts() { + ASSERT(adding_); + if (!adding_) + return; + + std::stringstream ss; + if (!parts_.empty()) { + ss << "\r\n"; + } + ss << "--" << boundary_ << "--" << "\r\n"; + parts_.push_back(new MemoryStream(ss.str().data(), ss.str().size())); + + ASSERT(0 == current_); + ASSERT(0 == position_); + adding_ = false; + SignalEvent(this, SE_OPEN | SE_READ, 0); +} + +size_t MultipartStream::GetPartSize(const std::string& data, + const std::string& content_disposition, + const std::string& content_type) const { + size_t size = 0; + if (!parts_.empty()) { + size += 2; // for "\r\n"; + } + size += boundary_.size() + 4; // for "--boundary_\r\n"; + if (!content_disposition.empty()) { + // for ToString(HH_CONTENT_DISPOSITION): content_disposition\r\n + size += std::string(ToString(HH_CONTENT_DISPOSITION)).size() + 2 + + content_disposition.size() + 2; + } + if (!content_type.empty()) { + // for ToString(HH_CONTENT_TYPE): content_type\r\n + size += std::string(ToString(HH_CONTENT_TYPE)).size() + 2 + + content_type.size() + 2; + } + size += 2 + data.size(); // for \r\ndata + return size; +} + +size_t MultipartStream::GetEndPartSize() const { + size_t size = 0; + if (!parts_.empty()) { + size += 2; // for "\r\n"; + } + size += boundary_.size() + 6; // for "--boundary_--\r\n"; + return size; +} + +// +// StreamInterface +// + +StreamState MultipartStream::GetState() const { + if (adding_) { + return SS_OPENING; + } + return (current_ < parts_.size()) ? SS_OPEN : SS_CLOSED; +} + +StreamResult MultipartStream::Read(void* buffer, size_t buffer_len, + size_t* read, int* error) { + if (adding_) { + return SR_BLOCK; + } + size_t local_read; + if (!read) read = &local_read; + while (current_ < parts_.size()) { + StreamResult result = parts_[current_]->Read(buffer, buffer_len, read, + error); + if (SR_EOS != result) { + if (SR_SUCCESS == result) { + position_ += *read; + } + return result; + } + ++current_; + } + return SR_EOS; +} + +StreamResult MultipartStream::Write(const void* data, size_t data_len, + size_t* written, int* error) { + if (error) { + *error = -1; + } + return SR_ERROR; +} + +void MultipartStream::Close() { + for (size_t i = 0; i < parts_.size(); ++i) { + delete parts_[i]; + } + parts_.clear(); + adding_ = false; + current_ = 0; + position_ = 0; +} + +bool MultipartStream::SetPosition(size_t position) { + if (adding_) { + return false; + } + size_t part_size, part_offset = 0; + for (size_t i = 0; i < parts_.size(); ++i) { + if (!parts_[i]->GetSize(&part_size)) { + return false; + } + if (part_offset + part_size > position) { + for (size_t j = i+1; j < _min(parts_.size(), current_+1); ++j) { + if (!parts_[j]->Rewind()) { + return false; + } + } + if (!parts_[i]->SetPosition(position - part_offset)) { + return false; + } + current_ = i; + position_ = position; + return true; + } + part_offset += part_size; + } + return false; +} + +bool MultipartStream::GetPosition(size_t* position) const { + if (position) { + *position = position_; + } + return true; +} + +bool MultipartStream::GetSize(size_t* size) const { + size_t part_size, total_size = 0; + for (size_t i = 0; i < parts_.size(); ++i) { + if (!parts_[i]->GetSize(&part_size)) { + return false; + } + total_size += part_size; + } + if (size) { + *size = total_size; + } + return true; +} + +bool MultipartStream::GetAvailable(size_t* size) const { + if (adding_) { + return false; + } + size_t part_size, total_size = 0; + for (size_t i = current_; i < parts_.size(); ++i) { + if (!parts_[i]->GetAvailable(&part_size)) { + return false; + } + total_size += part_size; + } + if (size) { + *size = total_size; + } + return true; +} + +// +// StreamInterface Slots +// + +void MultipartStream::OnEvent(StreamInterface* stream, int events, int error) { + if (adding_ || (current_ >= parts_.size()) || (parts_[current_] != stream)) { + return; + } + SignalEvent(this, events, error); +} + +} // namespace rtc |