diff options
author | Vegard Storheil Eriksen <zyp@sakuya.local> | 2010-11-06 02:35:39 +0100 |
---|---|---|
committer | Vegard Storheil Eriksen <zyp@sakuya.local> | 2010-11-06 02:35:39 +0100 |
commit | cfef24ce8541ac3934ecfe7248a33d1099d94dfa (patch) | |
tree | 4335e25b6fd490fa8744fed82aa7273fc7a72395 | |
parent | df5932614261a825fb5a9283c321f47f7a198b24 (diff) |
First take on abstract ConnectionBase, ASIO listening and connection handling.
-rw-r--r-- | common/connectionbase.cpp | 16 | ||||
-rw-r--r-- | common/connectionbase.h | 40 | ||||
-rw-r--r-- | server/SConstruct | 8 | ||||
-rw-r--r-- | server/connection.cpp | 35 | ||||
-rw-r--r-- | server/connection.h | 38 | ||||
-rw-r--r-- | server/main.cpp | 58 | ||||
-rw-r--r-- | server/tcpserver.cpp | 28 | ||||
-rw-r--r-- | server/tcpserver.h | 22 |
8 files changed, 185 insertions, 60 deletions
diff --git a/common/connectionbase.cpp b/common/connectionbase.cpp new file mode 100644 index 0000000..b2147fa --- /dev/null +++ b/common/connectionbase.cpp @@ -0,0 +1,16 @@ +#include "connectionbase.h" + +#include <iostream> +#include <string> + +void ConnectionBase::connected() { + std::cout << "Connection established." << std::endl; + + write_data((uint8_t*)"Hei!\n", 5); + + request_data(10); +} + +void ConnectionBase::got_data(uint8_t* data, std::size_t bytes) { + std::cout << "Fikk data: " << std::string((char*)data, bytes) << std::endl; +} diff --git a/common/connectionbase.h b/common/connectionbase.h new file mode 100644 index 0000000..1bfc437 --- /dev/null +++ b/common/connectionbase.h @@ -0,0 +1,40 @@ +#ifndef CONNECTIONBASE_H +#define CONNECTIONBASE_H + +#include <stdint.h> +#include <cstdlib> + +// Poor excuse for a real Message class. +class Message { + public: + typedef Message* p; +}; + +class ConnectionBase { + protected: + //! Signal that connection is established and ready to transfer data. + void connected(); + + //! Deliver received data. + //! \param data Pointer to received data. Ownership is retained by caller. + //! \param bytes Size of data. + void got_data(uint8_t* data, std::size_t bytes); + + //! Called to request data. + //! \param bytes Amount of data requested. + virtual void request_data(std::size_t bytes) = 0; + + //! Called to write data. + //! \param data Pointer to data to send. Ownership is transferred to callee. + //! \param bytes Size of data. + virtual void write_data(uint8_t* data, std::size_t bytes) = 0; + + public: + //! Send a message. + void send(const Message::p& msg); + + //! Get received message or null if queue empty. + Message::p recv(); +}; + +#endif diff --git a/server/SConstruct b/server/SConstruct index d1def28..fe7244e 100644 --- a/server/SConstruct +++ b/server/SConstruct @@ -10,14 +10,14 @@ AddOption('--profiling', action = 'store_true') env.Append(LIBS = ['boost_system', 'pthread']) if not GetOption('release'): - env.Append(CPPFLAGS = ['-Wall', '-g']) + env.Append(CPPFLAGS = ['-Wall', '-g']) if GetOption('profiling'): - env.Append(CPPFLAGS = ['-pg']) - env.Append(LINKFLAGS = ['-pg']) + env.Append(CPPFLAGS = ['-pg']) + env.Append(LINKFLAGS = ['-pg']) Export('env') -env.Program('aotenjoud', Glob('*.cpp')) +env.Program('aotenjoud', Glob('*.cpp') + ['../common/connectionbase.cpp']) # vim: syn=python diff --git a/server/connection.cpp b/server/connection.cpp new file mode 100644 index 0000000..f846d3b --- /dev/null +++ b/server/connection.cpp @@ -0,0 +1,35 @@ +#include "connection.h" + +#include <boost/bind.hpp> + +Connection::Connection(boost::asio::io_service& io_service) : socket(io_service) { + +} + +void Connection::handle_read(uint8_t* data, std::size_t bytes) { + got_data(data, bytes); + + delete[] data; +} + +void Connection::handle_write() { + +} + +void Connection::request_data(std::size_t bytes) { + uint8_t* buf = new uint8_t[bytes]; + + boost::asio::async_read(socket, boost::asio::buffer(buf, bytes), + boost::bind(&Connection::handle_read, shared_from_this(), buf, bytes)); + + // boost::asio::placeholders::error +} + +void Connection::write_data(uint8_t* data, std::size_t bytes) { + boost::asio::async_write(socket, boost::asio::buffer(data, bytes), + boost::bind(&Connection::handle_write, shared_from_this())); +} + +Connection::p Connection::create(boost::asio::io_service& io_service) { + return Connection::p(new Connection(io_service)); +} diff --git a/server/connection.h b/server/connection.h new file mode 100644 index 0000000..aba7734 --- /dev/null +++ b/server/connection.h @@ -0,0 +1,38 @@ +#ifndef CONNECTION_H +#define CONNECTION_H + +#include <boost/asio.hpp> +#include <boost/enable_shared_from_this.hpp> + +#include "../common/connectionbase.h" + +class Connection : public ConnectionBase, public boost::enable_shared_from_this<Connection> { + private: + friend class TCPServer; + + boost::asio::ip::tcp::socket socket; + + Connection(boost::asio::io_service& io_service); + + private: + //! Callback for when data is read. + void handle_read(uint8_t* data, std::size_t bytes); + + //! Callback for when data is written. + void handle_write(); + + protected: + //! Implements request_data(). + virtual void request_data(std::size_t bytes); + + //! Implements write_data(). + virtual void write_data(uint8_t* data, std::size_t bytes); + + public: + typedef boost::shared_ptr<Connection> p; + + //! Constructs a new instance and returns a shared pointer. + static p create(boost::asio::io_service& io_service); +}; + +#endif diff --git a/server/main.cpp b/server/main.cpp index 9341623..3e311e5 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -1,67 +1,13 @@ #include <iostream> -#include <boost/bind.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/enable_shared_from_this.hpp> #include <boost/asio.hpp> -using boost::asio::ip::tcp; - -class tcp_connection : public boost::enable_shared_from_this<tcp_connection> { - public: - typedef boost::shared_ptr<tcp_connection> pointer; - - static pointer create(boost::asio::io_service& io_service) { - return pointer(new tcp_connection(io_service)); - } - - tcp::socket& socket() { - return socket_; - } - - void start() { - boost::asio::async_write(socket_, boost::asio::buffer("Hei!\n"), - boost::bind(&tcp_connection::handle_write, shared_from_this())); - } - - private: - tcp::socket socket_; - - tcp_connection(boost::asio::io_service& io_service) : socket_(io_service) { - } - - void handle_write() { - } -}; - -class tcp_server { - public: - tcp_server(boost::asio::io_service& io_service) - : acceptor_(io_service, tcp::endpoint(tcp::v4(), 12345)) { - start_accept(); - } - - private: - tcp::acceptor acceptor_; - - void start_accept() { - tcp_connection::pointer new_connection = tcp_connection::create(acceptor_.io_service()); - - acceptor_.async_accept(new_connection->socket(), boost::bind(&tcp_server::handle_accept, this, new_connection, boost::asio::placeholders::error)); - } - - void handle_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error) { - if(!error) { - new_connection->start(); - start_accept(); - } - } -}; +#include "tcpserver.h" int main() { try { boost::asio::io_service io_service; - tcp_server server(io_service); + TCPServer server(io_service); std::cout << "Listening to port 12345" << std::endl; diff --git a/server/tcpserver.cpp b/server/tcpserver.cpp new file mode 100644 index 0000000..528d1a2 --- /dev/null +++ b/server/tcpserver.cpp @@ -0,0 +1,28 @@ +#include "tcpserver.h" + +#include <boost/bind.hpp> + +TCPServer::TCPServer(boost::asio::io_service& io_service) + : acceptor_(io_service, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 12345)) { + + // Start listening for first connection attempt. + listen(); +} + +void TCPServer::listen() { + Connection::p new_connection = Connection::create(acceptor_.io_service()); + + acceptor_.async_accept(new_connection->socket, + boost::bind(&TCPServer::handle_connection, this, new_connection, boost::asio::placeholders::error)); +} + +void TCPServer::handle_connection(Connection::p connection, const boost::system::error_code& error) { + if(error) { + return; + } + + connection->connected(); + + // Start listening for another connection attempt. + listen(); +}
\ No newline at end of file diff --git a/server/tcpserver.h b/server/tcpserver.h new file mode 100644 index 0000000..5d0cbba --- /dev/null +++ b/server/tcpserver.h @@ -0,0 +1,22 @@ +#ifndef TCPSERVER_H +#define TCPSERVER_H + +#include <boost/asio.hpp> + +#include "connection.h" + +class TCPServer { + private: + boost::asio::ip::tcp::acceptor acceptor_; + + //! Listen for incoming connection. + void listen(); + + //! Handle new connection. + void handle_connection(Connection::p connection, const boost::system::error_code& error); + + public: + TCPServer(boost::asio::io_service& io_service); +}; + +#endif |