diff --git a/CMakeLists.txt b/CMakeLists.txt
index 243001d1..09493a73 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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()
diff --git a/src/System/Event.cpp b/src/System/Event.cpp
new file mode 100644
index 00000000..ddc2a507
--- /dev/null
+++ b/src/System/Event.cpp
@@ -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 .
+
+#include "Event.h"
+#include
+#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();
+ }
+}
diff --git a/src/System/Event.h b/src/System/Event.h
new file mode 100644
index 00000000..50125024
--- /dev/null
+++ b/src/System/Event.h
@@ -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 .
+
+#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;
+};
diff --git a/src/System/System.cpp b/src/System/System.cpp
new file mode 100644
index 00000000..fd12d33c
--- /dev/null
+++ b/src/System/System.cpp
@@ -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 .
+
+#include "System.h"
+#include
+#include
+#include
+
+namespace {
+void contextProcedureStatic(intptr_t context) {
+ reinterpret_cast(context)->contextProcedure();
+}
+}
+
+System::System() {
+ ioService = new boost::asio::io_service;
+ work = new boost::asio::io_service::work(*static_cast(ioService));
+ currentContext = new boost::context::fcontext_t;
+}
+
+System::~System() {
+ assert(procedures.empty());
+ assert(resumingContexts.empty());
+ while (!contexts.empty()) {
+
+ delete static_cast(contexts.top());
+
+ contexts.pop();
+ }
+ delete static_cast(work);
+ if (!static_cast(ioService)->stopped()) {
+ static_cast(ioService)->stop();
+ }
+ delete static_cast(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&& procedure) {
+ procedures.emplace(std::move(procedure));
+}
+
+void System::wake() {
+ static_cast(ioService)->post([] {});
+}
+
+void System::yield() {
+ if (procedures.empty()) {
+ void* context;
+ for (;;) {
+ if (resumingContexts.empty()) {
+ boost::system::error_code errorCode;
+ static_cast(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(currentContext);
+ currentContext = context;
+#if (BOOST_VERSION >= 105600)
+ boost::context::jump_fcontext(oldContext, *static_cast(context), reinterpret_cast(this), false);
+#else
+ boost::context::jump_fcontext(oldContext, static_cast(context), reinterpret_cast(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(currentContext);
+ currentContext = context;
+#if (BOOST_VERSION >= 105600)
+ boost::context::jump_fcontext(oldContext, *static_cast(context), reinterpret_cast(this), false);
+#else
+ boost::context::jump_fcontext(oldContext, static_cast(context), reinterpret_cast(this), false);
+#endif
+ }
+}
+
+void System::contextProcedure() {
+ void* context = currentContext;
+ for (;;) {
+ assert(!procedures.empty());
+ std::function procedure = std::move(procedures.front());
+ procedures.pop();
+ procedure();
+ contexts.push(context);
+ yield();
+ }
+}
diff --git a/src/System/System.h b/src/System/System.h
new file mode 100644
index 00000000..712de348
--- /dev/null
+++ b/src/System/System.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+#include
+
+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&& procedure);
+ void yield();
+ void wake();
+
+ void contextProcedure();
+
+private:
+ void* ioService;
+ void* work;
+ std::stack contexts;
+ std::queue> procedures;
+ std::queue resumingContexts;
+ void* currentContext;
+};
diff --git a/src/System/TcpConnection.cpp b/src/System/TcpConnection.cpp
new file mode 100644
index 00000000..13a5a41b
--- /dev/null
+++ b/src/System/TcpConnection.cpp
@@ -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 .
+
+#include "TcpConnection.h"
+#include
+#include
+#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(socket);
+ }
+}
+
+TcpConnection& TcpConnection::operator=(TcpConnection&& other) {
+ if (system != nullptr) {
+ delete static_cast(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(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(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);
+}
diff --git a/src/System/TcpConnection.h b/src/System/TcpConnection.h
new file mode 100644
index 00000000..ce2829e9
--- /dev/null
+++ b/src/System/TcpConnection.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+
+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;
+};
diff --git a/src/System/TcpConnector.cpp b/src/System/TcpConnector.cpp
new file mode 100644
index 00000000..703a1f8d
--- /dev/null
+++ b/src/System/TcpConnector.cpp
@@ -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 .
+
+#include "TcpConnector.h"
+#include
+#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(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);
+}
diff --git a/src/System/TcpConnector.h b/src/System/TcpConnector.h
new file mode 100644
index 00000000..960d1f1f
--- /dev/null
+++ b/src/System/TcpConnector.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+
+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;
+};
diff --git a/src/System/TcpListener.cpp b/src/System/TcpListener.cpp
new file mode 100644
index 00000000..75071eac
--- /dev/null
+++ b/src/System/TcpListener.cpp
@@ -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 .
+
+#include "TcpListener.h"
+#include
+#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(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(listener);
+ }
+}
+
+TcpListener& TcpListener::operator=(TcpListener&& other) {
+ if (system != nullptr) {
+ delete static_cast(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(system->getIoService()));
+ boost::system::error_code errorCode;
+ static_cast(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);
+}
diff --git a/src/System/TcpListener.h b/src/System/TcpListener.h
new file mode 100644
index 00000000..6147257c
--- /dev/null
+++ b/src/System/TcpListener.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+
+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;
+};
diff --git a/src/System/TcpStream.cpp b/src/System/TcpStream.cpp
new file mode 100644
index 00000000..da058f4b
--- /dev/null
+++ b/src/System/TcpStream.cpp
@@ -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 .
+
+#include "TcpStream.h"
+
+#include
+
+TcpStreambuf::TcpStreambuf(TcpConnection& connection) : connection(connection) {
+ setg(&readBuf.front(), &readBuf.front(), &readBuf.front());
+ setp(reinterpret_cast(&writeBuf.front()), reinterpret_cast(&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(&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;
+}
diff --git a/src/System/TcpStream.h b/src/System/TcpStream.h
new file mode 100644
index 00000000..55c28d55
--- /dev/null
+++ b/src/System/TcpStream.h
@@ -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 .
+
+#pragma once
+
+#include
+#include
+
+#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 readBuf;
+ std::array writeBuf;
+};
diff --git a/src/System/Timer.cpp b/src/System/Timer.cpp
new file mode 100644
index 00000000..786d4485
--- /dev/null
+++ b/src/System/Timer.cpp
@@ -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 .
+
+#include "Timer.h"
+#include
+#include "System.h"
+
+Timer::Timer() : system(nullptr) {
+}
+
+Timer::Timer(System& system) : system(&system) {
+ timer = new boost::asio::steady_timer(*static_cast(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(timer);
+ }
+}
+
+Timer& Timer::operator=(Timer&& other) {
+ if (system != nullptr) {
+ delete static_cast(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(timer)->expires_from_now(time);
+ void* context = system->getCurrentContext();
+ boost::system::error_code errorCode;
+ static_cast(timer)->async_wait([&](const boost::system::error_code& callbackErrorCode) {
+ errorCode = callbackErrorCode;
+ system->pushContext(context);
+ });
+
+ system->yield();
+ if (errorCode) {
+ throw boost::system::system_error(errorCode);
+ }
+}
diff --git a/src/System/Timer.h b/src/System/Timer.h
new file mode 100644
index 00000000..317f87eb
--- /dev/null
+++ b/src/System/Timer.h
@@ -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 .
+
+#pragma once
+
+#include
+
+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;
+};