summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/webrtc/base/multipart.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/webrtc/base/multipart.cc')
-rw-r--r--chromium/third_party/webrtc/base/multipart.cc253
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