/* * Connection.h * * Copyright (C) 2008 Matthias Schiffer * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program. If not, see . */ #ifndef MAD_NET_CONNECTION_H_ #define MAD_NET_CONNECTION_H_ #include #include "Packet.h" #include #include #include #include namespace Mad { namespace Net { class ThreadManager; class Connection : boost::noncopyable { protected: friend class ThreadManager; enum State { DISCONNECTED, CONNECT, CONNECTED, DISCONNECT }; private: class Buffer { public: Buffer(const uint8_t *data0, std::size_t length) : data(new std::vector(data0, data0+length)), buffer(boost::asio::buffer(*data)) {} typedef boost::asio::const_buffer value_type; typedef const boost::asio::const_buffer* const_iterator; const boost::asio::const_buffer* begin() const { return &buffer; } const boost::asio::const_buffer* end() const { return &buffer + 1; } private: boost::shared_ptr > data; boost::asio::const_buffer buffer; }; boost::condition_variable_any stateChanged; State state; std::vector receiveBuffer; std::size_t received; Packet::Data header; boost::signal1 receiveSignal; boost::signal0 connectedSignal; boost::signal0 disconnectedSignal; bool receiving; unsigned long sending; void enterReceiveLoop(); void handleHeaderReceive(const std::vector &data); void handleDataReceive(const std::vector &data); void handleRead(const boost::system::error_code& error, std::size_t bytes_transferred, std::size_t length, const boost::function1& > ¬ify); void handleWrite(const boost::system::error_code& error, std::size_t); void handleShutdown(const boost::system::error_code& error); void rawReceive(std::size_t length, const boost::function1& > ¬ify); void rawSend(const uint8_t *data, std::size_t length); protected: static boost::asio::io_service ioService; boost::shared_mutex connectionLock; boost::asio::ssl::stream socket; boost::asio::ip::tcp::endpoint peer; void handleHandshake(const boost::system::error_code& error); bool _isConnected() const {return (state != DISCONNECTED);} bool _isConnecting() const { return (state == CONNECT); } bool _isDisconnecting() const { return (state == DISCONNECT); } void _setState(State newState) { state = newState; stateChanged.notify_all(); } void doDisconnect(); Connection(boost::asio::ssl::context &sslContext) : state(DISCONNECTED), receiveBuffer(1024*1024), socket(ioService, sslContext) {} public: virtual ~Connection(); bool isConnected() { boost::shared_lock lock(connectionLock); return _isConnected(); } bool isConnecting() { boost::shared_lock lock(connectionLock); return _isConnecting(); } bool isDisconnecting() { boost::shared_lock lock(connectionLock); return _isDisconnecting(); } void waitWhileConnecting() { boost::shared_lock lock(connectionLock); while(_isConnecting()) stateChanged.wait(lock); } void waitWhileConnected() { boost::shared_lock lock(connectionLock); while(_isConnected()) stateChanged.wait(lock); } /*const gnutls_datum_t* getCertificate() const { // TODO Thread-safeness return gnutls_certificate_get_ours(session); } const gnutls_datum_t* getPeerCertificate() const { // TODO Thread-safeness unsigned int n; return gnutls_certificate_get_peers(session, &n); }*/ boost::asio::ip::tcp::endpoint getPeer() { boost::shared_lock lock(connectionLock); return peer; } void disconnect(); bool send(const Packet &packet); boost::signal1& signalReceive() {return receiveSignal;} boost::signal0& signalConnected() {return connectedSignal;} boost::signal0& signalDisconnected() {return disconnectedSignal;} }; } } #endif /*MAD_NET_CONNECTION_H_*/