blob: a1ad4b2f52d13f119b65aeae0aeff8e510cfaa6b [file] [log] [blame]
// 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 <string>
#include "base/logging.h"
#include "base/message_loop.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::RunWithParams(const Tuple1<int>& params) {
int status = params.a;
LOG(INFO) << "Callback! " << status;
if (status < 0)
MessageLoop::current()->Quit();
}
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),
ALLOW_THIS_IN_INITIALIZER_LIST(
read_callback_(this, &EchoServer::OnReadComplete)),
ALLOW_THIS_IN_INITIALIZER_LIST(
write_callback_(this, &EchoServer::OnWriteComplete)) {
}
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, &write_callback_);
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(),
&write_callback_);
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, &read_callback_);
if (rv == ERR_IO_PENDING)
return;
OnReadComplete(rv); // Complete the read manually
} while (rv > 0);
}
} // namespace net