| // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "net/test/embedded_test_server/http_connection.h" | |
| #include <utility> | |
| #include "net/base/net_errors.h" | |
| #include "net/socket/stream_socket.h" | |
| #include "net/traffic_annotation/network_traffic_annotation_test_helper.h" | |
| namespace net { | |
| namespace test_server { | |
| HttpConnection::HttpConnection(std::unique_ptr<StreamSocket> socket, | |
| const HandleRequestCallback& callback) | |
| : socket_(std::move(socket)), | |
| callback_(callback), | |
| read_buf_(base::MakeRefCounted<IOBufferWithSize>(4096)), | |
| weak_factory_(this) {} | |
| HttpConnection::~HttpConnection() { | |
| weak_factory_.InvalidateWeakPtrs(); | |
| } | |
| void HttpConnection::SendResponseBytes(const std::string& response_string, | |
| const SendCompleteCallback& callback) { | |
| if (response_string.length() > 0) { | |
| scoped_refptr<DrainableIOBuffer> write_buf = | |
| base::MakeRefCounted<DrainableIOBuffer>( | |
| base::MakeRefCounted<StringIOBuffer>(response_string), | |
| response_string.length()); | |
| SendInternal(callback, write_buf); | |
| } else { | |
| callback.Run(); | |
| } | |
| } | |
| int HttpConnection::ReadData(CompletionOnceCallback callback) { | |
| return socket_->Read(read_buf_.get(), read_buf_->size(), std::move(callback)); | |
| } | |
| bool HttpConnection::ConsumeData(int size) { | |
| request_parser_.ProcessChunk(base::StringPiece(read_buf_->data(), size)); | |
| if (request_parser_.ParseRequest() == HttpRequestParser::ACCEPTED) { | |
| callback_.Run(this, request_parser_.GetRequest()); | |
| return true; | |
| } | |
| return false; | |
| } | |
| void HttpConnection::SendInternal(const base::Closure& callback, | |
| scoped_refptr<DrainableIOBuffer> buf) { | |
| while (buf->BytesRemaining() > 0) { | |
| int rv = socket_->Write(buf.get(), buf->BytesRemaining(), | |
| base::Bind(&HttpConnection::OnSendInternalDone, | |
| base::Unretained(this), callback, buf), | |
| TRAFFIC_ANNOTATION_FOR_TESTS); | |
| if (rv == ERR_IO_PENDING) | |
| return; | |
| if (rv < 0) | |
| break; | |
| buf->DidConsume(rv); | |
| } | |
| // The HttpConnection will be deleted by the callback since we only need to | |
| // serve a single request. | |
| callback.Run(); | |
| } | |
| void HttpConnection::OnSendInternalDone(const base::Closure& callback, | |
| scoped_refptr<DrainableIOBuffer> buf, | |
| int rv) { | |
| if (rv < 0) { | |
| callback.Run(); | |
| return; | |
| } | |
| buf->DidConsume(rv); | |
| SendInternal(callback, buf); | |
| } | |
| base::WeakPtr<HttpConnection> HttpConnection::GetWeakPtr() { | |
| return weak_factory_.GetWeakPtr(); | |
| } | |
| } // namespace test_server | |
| } // namespace net |