diff options
Diffstat (limited to 'src/Net/Connection.h')
-rw-r--r-- | src/Net/Connection.h | 144 |
1 files changed, 51 insertions, 93 deletions
diff --git a/src/Net/Connection.h b/src/Net/Connection.h index a0b95ea..303485d 100644 --- a/src/Net/Connection.h +++ b/src/Net/Connection.h @@ -24,155 +24,111 @@ #include "Packet.h" -#include <queue> -#include <string> -#include <gnutls/gnutls.h> -#include <poll.h> +#include <boost/asio.hpp> +#include <boost/asio/ssl.hpp> #include <boost/signal.hpp> -#include <boost/thread/mutex.hpp> -#include <boost/thread/shared_mutex.hpp> -#include <iostream> +#include <boost/thread/shared_mutex.hpp> namespace Mad { namespace Net { -class IPAddress; -class Packet; +class ThreadManager; -class Connection { +class Connection : boost::noncopyable { private: - class StaticInit { - public: - StaticInit() { - gnutls_global_init(); - } + friend class ThreadManager; - ~StaticInit() { - gnutls_global_deinit(); - } - }; - static StaticInit staticInit; + class Buffer { + public: + Buffer(const uint8_t *data0, std::size_t length) : data(new std::vector<uint8_t>(data0, data0+length)), buffer(boost::asio::buffer(*data)) {} - struct Transmission { - unsigned long length; - unsigned long transmitted; + typedef boost::asio::const_buffer value_type; + typedef const boost::asio::const_buffer* const_iterator; - uint8_t *data; + const boost::asio::const_buffer* begin() const { return &buffer; } + const boost::asio::const_buffer* end() const { return &buffer + 1; } - boost::function2<void,const void*,unsigned long> notify; + private: + boost::shared_ptr<std::vector<uint8_t> > data; + boost::asio::const_buffer buffer; }; - boost::mutex receiveLock; - Transmission transR; - boost::mutex sendLock; - std::queue<Transmission> transS; + std::vector<boost::uint8_t> receiveBuffer; + std::size_t received; Packet::Data header; - boost::signal1<void,const Packet&> receiveSignal; + boost::signal1<void, const Packet&> receiveSignal; boost::signal0<void> connectedSignal; boost::signal0<void> disconnectedSignal; - void doHandshake(); - - void packetHeaderReceiveHandler(const void *data, unsigned long length); - void packetDataReceiveHandler(const void *data, unsigned long length); + bool receiving; + unsigned long sending; - void doReceive(); - void doSend(); - - void doBye(); - - void doDisconnect(); + void enterReceiveLoop(); - bool _receiveComplete() const { - return (transR.length == transR.transmitted); - } + void handleHeaderReceive(const std::vector<boost::uint8_t> &data); + void handleDataReceive(const std::vector<boost::uint8_t> &data); - bool _sendQueueEmpty() const {return transS.empty();} + void handleRead(const boost::system::error_code& error, std::size_t bytes_transferred, std::size_t length, const boost::function1<void, const std::vector<boost::uint8_t>& > ¬ify); + void handleWrite(const boost::system::error_code& error, std::size_t); - void bye(); + void handleShutdown(const boost::system::error_code& error); - // Prevent shallow copy - Connection(const Connection &o); - Connection& operator=(const Connection &o); + void rawReceive(std::size_t length, const boost::function1<void, const std::vector<boost::uint8_t>& > ¬ify); + void rawSend(const uint8_t *data, std::size_t length); protected: - struct ConnectionHeader { - uint8_t m; - uint8_t a; - uint8_t d; - uint8_t type; - - uint8_t versionMajor; - uint8_t versionMinor; - uint8_t protVerMin; - uint8_t protVerMax; - }; + static boost::asio::io_service ioService; - boost::shared_mutex stateLock; + boost::shared_mutex connectionLock; enum State { - DISCONNECTED, CONNECT, HANDSHAKE, CONNECTION_HEADER, PACKET_HEADER, PACKET_DATA, DISCONNECT, BYE + DISCONNECTED, CONNECT, CONNECTED, DISCONNECT } state; - int sock; - gnutls_session_t session; - gnutls_certificate_credentials_t x509_cred; - IPAddress *peer; + boost::asio::ssl::stream<boost::asio::ip::tcp::socket> socket; + boost::asio::ip::tcp::endpoint peer; - void handshake(); - - virtual void connectionHeader() = 0; - - bool rawReceive(unsigned long length, const boost::function2<void,const void*,unsigned long> ¬ify); - bool rawSend(const uint8_t *data, unsigned long length); - - void enterReceiveLoop(); - - void sendReceive(short events); + void handleHandshake(const boost::system::error_code& error); bool _isConnected() const {return (state != DISCONNECTED);} bool _isConnecting() const { - return (state == CONNECT || state == HANDSHAKE || state == CONNECTION_HEADER); + return (state == CONNECT); } bool _isDisconnecting() const { - return (state == DISCONNECT || state == BYE); + return (state == DISCONNECT); } - void updateEvents(); - - public: - Connection() : state(DISCONNECTED), peer(0) { - transR.length = transR.transmitted = 0; - transR.data = 0; + void doDisconnect(); - gnutls_certificate_allocate_credentials(&x509_cred); - } + Connection(boost::asio::ssl::context &sslContext) : + receiveBuffer(1024*1024), state(DISCONNECTED), socket(ioService, sslContext) {} + public: virtual ~Connection(); bool isConnected() { - boost::shared_lock<boost::shared_mutex> lock(stateLock); + boost::shared_lock<boost::shared_mutex> lock(connectionLock); return _isConnected(); } bool isConnecting() { - boost::shared_lock<boost::shared_mutex> lock(stateLock); + boost::shared_lock<boost::shared_mutex> lock(connectionLock); return _isConnecting(); } bool isDisconnecting() { - boost::shared_lock<boost::shared_mutex> lock(stateLock); + boost::shared_lock<boost::shared_mutex> lock(connectionLock); return _isDisconnecting(); } - const gnutls_datum_t* getCertificate() const { + /*const gnutls_datum_t* getCertificate() const { // TODO Thread-safeness return gnutls_certificate_get_ours(session); } @@ -181,16 +137,18 @@ class Connection { // TODO Thread-safeness unsigned int n; return gnutls_certificate_get_peers(session, &n); - } + }*/ - // TODO Thread-safeness - const IPAddress* getPeer() const {return peer;} + boost::asio::ip::tcp::endpoint getPeer() { + boost::shared_lock<boost::shared_mutex> lock(connectionLock); + return peer; + } void disconnect(); bool send(const Packet &packet); - boost::signal1<void,const Packet&>& signalReceive() {return receiveSignal;} + boost::signal1<void, const Packet&>& signalReceive() {return receiveSignal;} boost::signal0<void>& signalConnected() {return connectedSignal;} boost::signal0<void>& signalDisconnected() {return disconnectedSignal;} }; |