/* * 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 "Packet.h" #include #include #include #include #include namespace Mad { namespace Net { class IPAddress; class Packet; class Connection { private: struct Transmission { unsigned long length; unsigned long transmitted; uint8_t *data; sigc::slot notify; }; enum State { DISCONNECTED, HANDSHAKE, CONNECTION_HEADER, PACKET_HEADER, PACKET_DATA, DISCONNECT, BYE } state; Transmission transR; std::queue transS; Packet::Data header; sigc::signal signal; void doHandshake(); void packetHeaderReceiveHandler(const void *data, unsigned long length); void packetDataReceiveHandler(const void *data, unsigned long length); void doReceive(); void doSend(); void doBye(); void doDisconnect(); bool receiveComplete() const { return (transR.length == transR.transmitted); } void bye(); void updateEvents() const; // Prevent shallow copy Connection(const Connection &o); Connection& operator=(const Connection &o); 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; }; int sock; gnutls_session_t session; gnutls_certificate_credentials_t x509_cred; IPAddress *peer; bool authenticated, identified; void handshake(); virtual void connectionHeader() = 0; bool rawReceive(unsigned long length, const sigc::slot ¬ify); bool rawSend(const uint8_t *data, unsigned long length); bool enterReceiveLoop(); public: Connection() : state(DISCONNECTED), peer(0), authenticated(false), identified(false) { transR.length = transR.transmitted = 0; transR.data = 0; gnutls_certificate_allocate_credentials(&x509_cred); } virtual ~Connection(); bool isConnected() const {return (state != DISCONNECTED);} bool isConnecting() const { return (state == HANDSHAKE || state == CONNECTION_HEADER); } bool isDisconnecting() const { return (state == DISCONNECT || state == BYE); } bool isAuthenticated() const {return authenticated;} void setAuthenticated() {authenticated = true;} bool isIdentified() const {return identified;} void setIdentified() {identified = true;} const gnutls_datum_t* getCertificate() { return gnutls_certificate_get_ours(session); } const gnutls_datum_t* getPeerCertificate() { unsigned int n; return gnutls_certificate_get_peers(session, &n); } const IPAddress* getPeer() {return peer;} int getSocket() const {return sock;} void disconnect(); bool send(const Packet &packet); void sendReceive(short events); bool sendQueueEmpty() const {return transS.empty();} sigc::signal signalReceive() const {return signal;} static void init() { gnutls_global_init(); } static void deinit() { gnutls_global_deinit(); } }; } } #endif /*MAD_NET_CONNECTION_H_*/