summaryrefslogtreecommitdiffstats
path: root/net/curvecp/test_client.cc
diff options
context:
space:
mode:
authormbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 10:36:56 +0000
committermbelshe@google.com <mbelshe@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-05-18 10:36:56 +0000
commitb690e18ca906d699e05cddae14250ab40439fee3 (patch)
treed34539a899c988f422f1235c7b52c2d1eb81d7ba /net/curvecp/test_client.cc
parent51c0220843bfc1939d2f1525f0fc0192b4926369 (diff)
downloadchromium_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.cc178
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