New TCP server

This commit is contained in:
jezal 2014-09-15 14:48:45 +04:00
parent 6b1858d965
commit 6d741947cb
15 changed files with 950 additions and 1 deletions

View file

@ -83,7 +83,7 @@ if(STATIC)
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_STATIC_RUNTIME ON)
endif()
find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options)
find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options coroutine context)
if((${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54))
message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA")
endif()

98
src/System/Event.cpp Normal file
View file

@ -0,0 +1,98 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "Event.h"
#include <cassert>
#include "System.h"
struct Event::Waiter {
Event::Waiter* next;
void* context;
};
Event::Event() : system(nullptr) {
}
Event::Event(System& system) : system(&system), first(nullptr), state(false) {
}
Event::Event(Event&& other) : system(other.system) {
if (other.system != nullptr) {
first = other.first;
if (other.first != nullptr) {
last = other.last;
}
state = other.state;
other.system = nullptr;
}
}
Event::~Event() {
assert(first == nullptr);
}
Event& Event::operator=(Event&& other) {
assert(first == nullptr);
system = other.system;
if (other.system != nullptr) {
first = other.first;
if (other.first != nullptr) {
last = other.last;
}
state = other.state;
other.system = nullptr;
}
return *this;
}
bool Event::get() const {
assert(system != nullptr);
return state;
}
void Event::clear() {
assert(system != nullptr);
state = false;
}
void Event::set() {
assert(system != nullptr);
state = true;
for (Waiter* waiter = first; waiter != nullptr; waiter = waiter->next) {
system->pushContext(waiter->context);
}
first = nullptr;
}
void Event::wait() {
assert(system != nullptr);
Waiter waiter = {nullptr, system->getCurrentContext()};
if (first != nullptr) {
last->next = &waiter;
} else {
first = &waiter;
}
last = &waiter;
while (!state) {
system->yield();
}
}

43
src/System/Event.h Normal file
View file

@ -0,0 +1,43 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
class System;
class Event {
public:
Event();
explicit Event(System& system);
Event(const Event&) = delete;
Event(Event&& other);
~Event();
Event& operator=(const Event&) = delete;
Event& operator=(Event&& other);
bool get() const;
void clear();
void set();
void wait();
private:
struct Waiter;
System* system;
Waiter* first;
Waiter* last;
bool state;
};

133
src/System/System.cpp Normal file
View file

@ -0,0 +1,133 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "System.h"
#include <iostream>
#include <boost/asio/spawn.hpp>
#include <boost/context/fcontext.hpp>
namespace {
void contextProcedureStatic(intptr_t context) {
reinterpret_cast<System*>(context)->contextProcedure();
}
}
System::System() {
ioService = new boost::asio::io_service;
work = new boost::asio::io_service::work(*static_cast<boost::asio::io_service*>(ioService));
currentContext = new boost::context::fcontext_t;
}
System::~System() {
assert(procedures.empty());
assert(resumingContexts.empty());
while (!contexts.empty()) {
delete static_cast<boost::context::fcontext_t*>(contexts.top());
contexts.pop();
}
delete static_cast<boost::asio::io_service::work*>(work);
if (!static_cast<boost::asio::io_service*>(ioService)->stopped()) {
static_cast<boost::asio::io_service*>(ioService)->stop();
}
delete static_cast<boost::asio::io_service*>(ioService);
}
void* System::getCurrentContext() const {
return currentContext;
}
void* System::getIoService() {
return ioService;
}
void System::pushContext(void* context) {
resumingContexts.push(context);
}
void System::spawn(std::function<void()>&& procedure) {
procedures.emplace(std::move(procedure));
}
void System::wake() {
static_cast<boost::asio::io_service*>(ioService)->post([] {});
}
void System::yield() {
if (procedures.empty()) {
void* context;
for (;;) {
if (resumingContexts.empty()) {
boost::system::error_code errorCode;
static_cast<boost::asio::io_service*>(ioService)->run_one(errorCode);
if (errorCode) {
std::cerr << "boost::asio::io_service::run_onw failed, result=" << errorCode << '.' << std::endl;
throw std::runtime_error("System::yield");
}
} else {
context = resumingContexts.front();
resumingContexts.pop();
break;
}
}
if (context != currentContext) {
boost::context::fcontext_t* oldContext = static_cast<boost::context::fcontext_t*>(currentContext);
currentContext = context;
#if (BOOST_VERSION >= 105600)
boost::context::jump_fcontext(oldContext, *static_cast<boost::context::fcontext_t*>(context), reinterpret_cast<intptr_t>(this), false);
#else
boost::context::jump_fcontext(oldContext, static_cast<boost::context::fcontext_t*>(context), reinterpret_cast<intptr_t>(this), false);
#endif
}
} else {
void* context;
if (contexts.empty()) {
#if (BOOST_VERSION >= 105600)
context = new boost::context::fcontext_t(boost::context::make_fcontext(new uint8_t[65536] + 65536, 65536, contextProcedureStatic));
#else
context = new boost::context::fcontext_t(*boost::context::make_fcontext(new uint8_t[65536] + 65536, 65536, contextProcedureStatic));
#endif
} else {
context = contexts.top();
contexts.pop();
}
boost::context::fcontext_t* oldContext = static_cast<boost::context::fcontext_t*>(currentContext);
currentContext = context;
#if (BOOST_VERSION >= 105600)
boost::context::jump_fcontext(oldContext, *static_cast<boost::context::fcontext_t*>(context), reinterpret_cast<intptr_t>(this), false);
#else
boost::context::jump_fcontext(oldContext, static_cast<boost::context::fcontext_t*>(context), reinterpret_cast<intptr_t>(this), false);
#endif
}
}
void System::contextProcedure() {
void* context = currentContext;
for (;;) {
assert(!procedures.empty());
std::function<void()> procedure = std::move(procedures.front());
procedures.pop();
procedure();
contexts.push(context);
yield();
}
}

46
src/System/System.h Normal file
View file

@ -0,0 +1,46 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <functional>
#include <queue>
#include <stack>
class System {
public:
System();
System(const System&) = delete;
~System();
System& operator=(const System&) = delete;
void* getCurrentContext() const;
void* getIoService();
void pushContext(void* context);
void spawn(std::function<void()>&& procedure);
void yield();
void wake();
void contextProcedure();
private:
void* ioService;
void* work;
std::stack<void*> contexts;
std::queue<std::function<void()>> procedures;
std::queue<void*> resumingContexts;
void* currentContext;
};

View file

@ -0,0 +1,110 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "TcpConnection.h"
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
#include "System.h"
TcpConnection::TcpConnection() : system(nullptr) {
}
TcpConnection::TcpConnection(System& system, void* socket) : system(&system), socket(socket), stopped(false) {
}
TcpConnection::TcpConnection(TcpConnection&& other) : system(other.system) {
if (other.system != nullptr) {
socket = other.socket;
stopped = other.stopped;
other.system = nullptr;
}
}
TcpConnection::~TcpConnection() {
if (system != nullptr) {
delete static_cast<boost::asio::ip::tcp::socket*>(socket);
}
}
TcpConnection& TcpConnection::operator=(TcpConnection&& other) {
if (system != nullptr) {
delete static_cast<boost::asio::ip::tcp::socket*>(socket);
}
system = other.system;
if (other.system != nullptr) {
socket = other.socket;
stopped = other.stopped;
other.system = nullptr;
}
return *this;
}
void TcpConnection::start() {
stopped = false;
}
void TcpConnection::stop() {
stopped = true;
}
size_t TcpConnection::read(uint8_t* data, size_t size) {
assert(system != nullptr);
if (stopped) {
throw std::runtime_error("Stopped");
}
void* context = system->getCurrentContext();
boost::system::error_code errorCode;
std::size_t transferred;
static_cast<boost::asio::ip::tcp::socket*>(socket)->async_read_some(boost::asio::buffer(data, size), [&](const boost::system::error_code& callbackErrorCode, std::size_t callbackTransferred) {
errorCode = callbackErrorCode;
transferred = callbackTransferred;
system->pushContext(context);
});
system->yield();
if (errorCode) {
throw boost::system::system_error(errorCode);
}
return transferred;
}
void TcpConnection::write(const uint8_t* data, size_t size) {
assert(system != nullptr);
if (stopped) {
throw std::runtime_error("Stopped");
}
void* context = system->getCurrentContext();
boost::system::error_code errorCode;
std::size_t transferred;
boost::asio::async_write(*static_cast<boost::asio::ip::tcp::socket*>(socket), boost::asio::buffer(data, size), [&](const boost::system::error_code& callbackErrorCode, std::size_t callbackTransferred) {
errorCode = callbackErrorCode;
transferred = callbackTransferred;
system->pushContext(context);
});
system->yield();
if (errorCode) {
throw boost::system::system_error(errorCode);
}
assert(transferred == size);
}

View file

@ -0,0 +1,47 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <cstddef>
#include <cstdint>
class System;
class TcpConnection {
public:
TcpConnection();
TcpConnection(const TcpConnection&) = delete;
TcpConnection(TcpConnection&& other);
~TcpConnection();
TcpConnection& operator=(const TcpConnection&) = delete;
TcpConnection& operator=(TcpConnection&& other);
void start();
void stop();
std::size_t read(uint8_t* data, std::size_t size);
void write(const uint8_t* data, std::size_t size);
private:
friend class TcpConnector;
friend class TcpListener;
explicit TcpConnection(System& system, void* socket);
System* system;
void* socket;
bool stopped;
};

View file

@ -0,0 +1,67 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "TcpConnector.h"
#include <boost/asio/ip/tcp.hpp>
#include "System.h"
#include "TcpConnection.h"
TcpConnector::TcpConnector() : system(nullptr) {
}
TcpConnector::TcpConnector(System& system, const std::string& address, uint16_t port) : system(&system), m_address(address), m_port(port) { }
TcpConnector::TcpConnector(TcpConnector&& other) : system(other.system) {
if (other.system != nullptr) {
m_address = other.m_address;
m_port = other.m_port;
other.system = nullptr;
}
}
TcpConnector::~TcpConnector() {
}
TcpConnector& TcpConnector::operator=(TcpConnector&& other) {
system = other.system;
if (other.system != nullptr) {
m_address = other.m_address;
m_port = other.m_port;
other.system = nullptr;
}
return *this;
}
TcpConnection TcpConnector::connect() {
assert(system != nullptr);
void* context = system->getCurrentContext();
boost::asio::ip::tcp::socket* socket = new boost::asio::ip::tcp::socket(*static_cast<boost::asio::io_service*>(system->getIoService()));
boost::system::error_code errorCode;
socket->async_connect(boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(m_address), m_port), [&](const boost::system::error_code& callbackErrorCode) {
errorCode = callbackErrorCode;
system->pushContext(context);
});
system->yield();
if (errorCode) {
delete socket;
throw boost::system::system_error(errorCode);
}
return TcpConnection(*system, socket);
}

41
src/System/TcpConnector.h Normal file
View file

@ -0,0 +1,41 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <cstdint>
#include <string>
class System;
class TcpConnection;
class TcpConnector {
public:
TcpConnector();
TcpConnector(System& system, const std::string& address, uint16_t port);
TcpConnector(const TcpConnector&) = delete;
TcpConnector(TcpConnector&& other);
~TcpConnector();
TcpConnector& operator=(const TcpConnector&) = delete;
TcpConnector& operator=(TcpConnector&& other);
TcpConnection connect();
private:
System* system;
std::string m_address;
uint16_t m_port;
};

View file

@ -0,0 +1,88 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "TcpListener.h"
#include <boost/asio/ip/tcp.hpp>
#include "System.h"
#include "TcpConnection.h"
TcpListener::TcpListener() : system(nullptr) {
}
TcpListener::TcpListener(System& system, const std::string& address, uint16_t port) : system(&system), stopped(false) {
listener = new boost::asio::ip::tcp::acceptor(*static_cast<boost::asio::io_service*>(system.getIoService()), boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(address), port), true);
}
TcpListener::TcpListener(TcpListener&& other) : system(other.system) {
if (other.system != nullptr) {
listener = other.listener;
stopped = other.stopped;
other.system = nullptr;
}
}
TcpListener::~TcpListener() {
if (system != nullptr) {
delete static_cast<boost::asio::ip::tcp::acceptor*>(listener);
}
}
TcpListener& TcpListener::operator=(TcpListener&& other) {
if (system != nullptr) {
delete static_cast<boost::asio::ip::tcp::acceptor*>(listener);
}
system = other.system;
if (other.system != nullptr) {
listener = other.listener;
stopped = other.stopped;
other.system = nullptr;
}
return *this;
}
void TcpListener::start() {
stopped = false;
}
void TcpListener::stop() {
stopped = true;
}
TcpConnection TcpListener::accept() {
assert(system != nullptr);
if (stopped) {
throw std::runtime_error("Stopped");
}
void* context = system->getCurrentContext();
boost::asio::ip::tcp::socket* socket = new boost::asio::ip::tcp::socket(*static_cast<boost::asio::io_service*>(system->getIoService()));
boost::system::error_code errorCode;
static_cast<boost::asio::ip::tcp::acceptor*>(listener)->async_accept(*socket, [&](const boost::system::error_code& callbackErrorCode) {
errorCode = callbackErrorCode;
system->pushContext(context);
});
system->yield();
if (errorCode) {
delete socket;
throw boost::system::system_error(errorCode);
}
return TcpConnection(*system, socket);
}

43
src/System/TcpListener.h Normal file
View file

@ -0,0 +1,43 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <cstdint>
#include <string>
class System;
class TcpConnection;
class TcpListener {
public:
TcpListener();
TcpListener(System& system, const std::string& address, uint16_t port);
TcpListener(const TcpListener&) = delete;
TcpListener(TcpListener&& other);
~TcpListener();
TcpListener& operator=(const TcpListener&) = delete;
TcpListener& operator=(TcpListener&& other);
void start();
void stop();
TcpConnection accept();
private:
System* system;
void* listener;
bool stopped;
};

82
src/System/TcpStream.cpp Normal file
View file

@ -0,0 +1,82 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "TcpStream.h"
#include <cstring>
TcpStreambuf::TcpStreambuf(TcpConnection& connection) : connection(connection) {
setg(&readBuf.front(), &readBuf.front(), &readBuf.front());
setp(reinterpret_cast<char*>(&writeBuf.front()), reinterpret_cast<char *>(&writeBuf.front() + writeBuf.max_size()));
}
TcpStreambuf::~TcpStreambuf() {
dumpBuffer();
}
std::streambuf::int_type TcpStreambuf::underflow() {
if (gptr() < egptr())
return traits_type::to_int_type(*gptr());
size_t bytesRead;
try {
bytesRead = connection.read(reinterpret_cast<uint8_t*>(&readBuf.front()), readBuf.max_size());
} catch (std::exception& ex) {
return traits_type::eof();
}
if (bytesRead == 0) {
return traits_type::eof();
}
setg(&readBuf.front(), &readBuf.front(), &readBuf.front() + bytesRead);
return traits_type::to_int_type(*gptr());
}
int TcpStreambuf::sync() {
return dumpBuffer() ? 0 : -1;
}
bool TcpStreambuf::dumpBuffer() {
try {
size_t count = pptr() - pbase();
connection.write(&writeBuf.front(), count);
pbump(-count);
} catch (std::exception&) {
return false;
}
return true;
}
std::streambuf::int_type TcpStreambuf::overflow(std::streambuf::int_type ch) {
if (ch == traits_type::eof()) {
return traits_type::eof();
}
if (pptr() == epptr()) {
if (!dumpBuffer()) {
return traits_type::eof();
}
}
*pptr() = ch;
pbump(1);
return ch;
}

43
src/System/TcpStream.h Normal file
View file

@ -0,0 +1,43 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <streambuf>
#include <array>
#include "TcpConnection.h"
class TcpStreambuf : public std::streambuf {
public:
TcpStreambuf(TcpConnection& connection);
TcpStreambuf(const TcpStreambuf&) = delete;
virtual ~TcpStreambuf();
private:
std::streambuf::int_type underflow() override;
std::streambuf::int_type overflow(std::streambuf::int_type ch) override;
int sync() override;
bool dumpBuffer();
TcpConnection& connection;
std::array<char, 4096> readBuf;
std::array<uint8_t, /*1024*/ 16> writeBuf;
};

70
src/System/Timer.cpp Normal file
View file

@ -0,0 +1,70 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#include "Timer.h"
#include <boost/asio/steady_timer.hpp>
#include "System.h"
Timer::Timer() : system(nullptr) {
}
Timer::Timer(System& system) : system(&system) {
timer = new boost::asio::steady_timer(*static_cast<boost::asio::io_service*>(system.getIoService()));
}
Timer::Timer(Timer&& other) : system(other.system) {
if (other.system != nullptr) {
timer = other.timer;
other.system = nullptr;
}
}
Timer::~Timer() {
if (system != nullptr) {
delete static_cast<boost::asio::steady_timer*>(timer);
}
}
Timer& Timer::operator=(Timer&& other) {
if (system != nullptr) {
delete static_cast<boost::asio::steady_timer*>(timer);
}
system = other.system;
if (other.system != nullptr) {
timer = other.timer;
other.system = nullptr;
}
return *this;
}
void Timer::sleep(std::chrono::milliseconds time) {
assert(system != nullptr);
static_cast<boost::asio::steady_timer*>(timer)->expires_from_now(time);
void* context = system->getCurrentContext();
boost::system::error_code errorCode;
static_cast<boost::asio::steady_timer*>(timer)->async_wait([&](const boost::system::error_code& callbackErrorCode) {
errorCode = callbackErrorCode;
system->pushContext(context);
});
system->yield();
if (errorCode) {
throw boost::system::system_error(errorCode);
}
}

38
src/System/Timer.h Normal file
View file

@ -0,0 +1,38 @@
// Copyright (c) 2012-2014, The CryptoNote developers, The Bytecoin developers
//
// This file is part of Bytecoin.
//
// Bytecoin is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Bytecoin is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with Bytecoin. If not, see <http://www.gnu.org/licenses/>.
#pragma once
#include <chrono>
class System;
class Timer {
public:
Timer();
explicit Timer(System& system);
Timer(const Timer&) = delete;
Timer(Timer&& other);
~Timer();
Timer& operator=(const Timer&) = delete;
Timer& operator=(Timer&& other);
void sleep(std::chrono::milliseconds time);
private:
System* system;
void* timer;
};