// 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_server.h" #include #include "base/logging.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" #include "net/base/net_util.h" #include "net/curvecp/curvecp_server_socket.h" namespace net { TestServer::TestServer() : socket_(NULL), errors_(0) { } TestServer::~TestServer() { if (socket_) { socket_->Close(); socket_ = NULL; } } bool TestServer::Start(int port) { IPAddressNumber ip_number; std::string ip_str("0.0.0.0"); if (!ParseIPLiteralToNumber(ip_str, &ip_number)) { LOG(ERROR) << "Bad IP Address"; return false; } IPEndPoint bind_address(ip_number, port); DCHECK(!socket_); socket_ = new CurveCPServerSocket(NULL, NetLog::Source()); int rv = socket_->Listen(bind_address, this); if (rv < ERR_IO_PENDING) { LOG(ERROR) << "Listen on port " << port << " failed: " << rv; return false; } return true; } void TestServer::OnAccept(CurveCPServerSocket* new_socket) { DCHECK(new_socket); LOG(ERROR) << "Accepted socket! Starting Echo Server"; EchoServer* new_server = new EchoServer(); new_server->Start(new_socket); } EchoServer::EchoServer() : socket_(NULL), bytes_received_(0) { } EchoServer::~EchoServer() { } void EchoServer::Start(CurveCPServerSocket* socket) { DCHECK(!socket_); socket_ = socket; ReadData(); // Note: |this| could be deleted here. } void EchoServer::OnReadComplete(int result) { LOG(INFO) << "Read complete: " << result; if (result <= 0) { delete this; return; } bytes_received_ += result; LOG(INFO) << "Server received " << result << "(" << bytes_received_ << ")"; if (!received_stream_.VerifyBytes(read_buffer_->data(), result)) { LOG(ERROR) << "Server Received corrupt receive data!"; delete this; return; } // Echo the read data back here. DCHECK(!write_buffer_.get()); write_buffer_ = new DrainableIOBuffer(read_buffer_, result); int rv = socket_->Write(write_buffer_, result, base::Bind(&EchoServer::OnWriteComplete, base::Unretained(this))); if (rv == ERR_IO_PENDING) return; OnWriteComplete(rv); } void EchoServer::OnWriteComplete(int result) { if (result <= 0) { delete this; return; } write_buffer_->DidConsume(result); while (write_buffer_->BytesRemaining()) { int rv = socket_->Write(write_buffer_, write_buffer_->BytesRemaining(), base::Bind(&EchoServer::OnWriteComplete, base::Unretained(this))); if (rv == ERR_IO_PENDING) return; OnWriteComplete(rv); } // Now we can read more data. write_buffer_ = NULL; // read_buffer_ = NULL; // ReadData(); } void EchoServer::ReadData() { DCHECK(!read_buffer_.get()); read_buffer_ = new IOBuffer(kMaxMessage); int rv; do { rv = socket_->Read(read_buffer_, kMaxMessage, base::Bind(&EchoServer::OnReadComplete, base::Unretained(this))); if (rv == ERR_IO_PENDING) return; OnReadComplete(rv); // Complete the read manually } while (rv > 0); } } // namespace net