diff options
author | mbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 10:36:56 +0000 |
---|---|---|
committer | mbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-18 10:36:56 +0000 |
commit | b690e18ca906d699e05cddae14250ab40439fee3 (patch) | |
tree | d34539a899c988f422f1235c7b52c2d1eb81d7ba /net/curvecp/test_client.cc | |
parent | 51c0220843bfc1939d2f1525f0fc0192b4926369 (diff) | |
download | chromium_src-b690e18ca906d699e05cddae14250ab40439fee3.zip chromium_src-b690e18ca906d699e05cddae14250ab40439fee3.tar.gz chromium_src-b690e18ca906d699e05cddae14250ab40439fee3.tar.bz2 |
An initial curvecp implementation. This implementation is not complete,
but is good enough to start collaboration.
BUG=none
TEST=curvecp_unittests
Review URL: http://codereview.chromium.org/7037022
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@85753 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/curvecp/test_client.cc')
-rw-r--r-- | net/curvecp/test_client.cc | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/net/curvecp/test_client.cc b/net/curvecp/test_client.cc new file mode 100644 index 0000000..f71f162 --- /dev/null +++ b/net/curvecp/test_client.cc @@ -0,0 +1,178 @@ +// Copyright (c) 2011 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/curvecp/test_client.h" + +#include <string> +#include <deque> +#include <vector> + +#include "base/logging.h" +#include "base/message_loop.h" +#include "net/base/address_list.h" +#include "net/base/host_resolver.h" +#include "net/base/io_buffer.h" +#include "net/base/net_errors.h" +#include "net/base/net_log.h" +#include "net/curvecp/curvecp_client_socket.h" + +namespace net { + +TestClient::TestClient() + : socket_(NULL), + errors_(0), + bytes_to_send_(0), + ALLOW_THIS_IN_INITIALIZER_LIST( + connect_callback_(this, &TestClient::OnConnectComplete)), + ALLOW_THIS_IN_INITIALIZER_LIST( + read_callback_(this, &TestClient::OnReadComplete)), + ALLOW_THIS_IN_INITIALIZER_LIST( + write_callback_(this, &TestClient::OnWriteComplete)), + finished_callback_(NULL) { +} + +TestClient::~TestClient() { + if (socket_) { + // TODO(mbelshe): The CurveCPClientSocket has a method called Disconnect. + // The CurveCPServerSocket has a method called Close. + // Unify them into either Close or Disconnect!!! + socket_->Disconnect(); + socket_ = NULL; + } +} + +bool TestClient::Start(const HostPortPair& server_host_port_pair, + int bytes_to_send, + CompletionCallback* callback) { + DCHECK(!socket_); + DCHECK(!finished_callback_); + + finished_callback_ = callback; + bytes_to_read_ = bytes_to_send_ = bytes_to_send; + + scoped_ptr<HostResolver> system_host_resolver( + CreateSystemHostResolver(1, NULL)); + SingleRequestHostResolver host_resolver(system_host_resolver.get()); + HostResolver::RequestInfo request(server_host_port_pair); + AddressList addresses; + int rv = host_resolver.Resolve(request, &addresses, NULL, BoundNetLog()); + if (rv != OK) { + LOG(ERROR) << "Could not resolve host"; + return false; + } + + socket_ = new CurveCPClientSocket(addresses, NULL, NetLog::Source()); + rv = socket_->Connect(&connect_callback_); + if (rv == ERR_IO_PENDING) + return true; + OnConnectComplete(rv); + return rv == OK; +} + +void TestClient::OnConnectComplete(int result) { + LOG(ERROR) << "Connect complete"; + if (result < 0) { + LOG(ERROR) << "Connect failure: " << result; + errors_++; + Finish(result); + return; + } + + DCHECK(bytes_to_send_); // We should have data to send. + ReadData(); + + DCHECK_EQ(bytes_to_send_, bytes_to_read_); + + SendData(); +} + +void TestClient::OnReadComplete(int result) { + if (result <= 0) { + LOG(ERROR) << "Read failure: " << result; + errors_++; + Finish(result); + return; + } + + if (!received_stream_.VerifyBytes(read_buffer_->data(), result)) { + if (!errors_) // Only log the first error. + LOG(ERROR) << "Client Received corrupt receive data!"; + errors_++; + } + + read_buffer_ = NULL; + bytes_to_read_ -= result; + + // Now read more data... + if (bytes_to_read_) + ReadData(); + else + Finish(OK); +} + +void TestClient::OnWriteComplete(int result) { + LOG(ERROR) << "Write complete (remaining = " << bytes_to_send_ << ")"; + if (result <= 0) { + errors_++; + Finish(result); + return; + } + + write_buffer_->DidConsume(result); + bytes_to_send_ -= result; + if (!write_buffer_->BytesRemaining()) + write_buffer_ = NULL; + + if (bytes_to_send_) + SendData(); +} + +void TestClient::ReadData() { + DCHECK(!read_buffer_.get()); + read_buffer_ = new IOBuffer(kMaxMessage); + + int rv; + do { + rv = socket_->Read(read_buffer_, kMaxMessage, &read_callback_); + if (rv == ERR_IO_PENDING) + return; + OnReadComplete(rv); // Complete the read manually + } while (rv > 0); +} + +void TestClient::SendData() { + DCHECK(bytes_to_send_); // We should have data to send. + const int kWriteChunkSize = 777; // 777 is more abusive + + do { + if (!write_buffer_.get()) { + int bytes_to_send = std::min(kWriteChunkSize, bytes_to_send_); + scoped_refptr<IOBuffer> buffer(new IOBuffer(bytes_to_send)); + sent_stream_.GetBytes(buffer->data(), bytes_to_send); + write_buffer_ = new DrainableIOBuffer(buffer, bytes_to_send); + } + + int rv = socket_->Write(write_buffer_, + write_buffer_->BytesRemaining(), + &write_callback_); + if (rv == ERR_IO_PENDING) + return; + + write_buffer_->DidConsume(rv); + bytes_to_send_ -= rv; + if (!write_buffer_->BytesRemaining()) + write_buffer_ = NULL; + } while (bytes_to_send_); +} + +void TestClient::Finish(int result) { + DCHECK(finished_callback_); + + LOG(ERROR) << "TestClient Done!"; + CompletionCallback* callback = finished_callback_; + finished_callback_ = NULL; + callback->Run(result); +} + +} // namespace net |