diff options
Diffstat (limited to 'src/Net')
-rw-r--r-- | src/Net/ClientConnection.cpp | 26 | ||||
-rw-r--r-- | src/Net/ClientConnection.h | 9 | ||||
-rw-r--r-- | src/Net/Connection.cpp | 2 | ||||
-rw-r--r-- | src/Net/Connection.h | 2 | ||||
-rw-r--r-- | src/Net/Makefile.am | 4 | ||||
-rw-r--r-- | src/Net/Makefile.in | 8 | ||||
-rw-r--r-- | src/Net/ServerConnection.cpp | 145 | ||||
-rw-r--r-- | src/Net/ServerConnection.h | 72 |
8 files changed, 255 insertions, 13 deletions
diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp index ea2e10e..1897b50 100644 --- a/src/Net/ClientConnection.cpp +++ b/src/Net/ClientConnection.cpp @@ -22,6 +22,7 @@ #include <cstring> #include <cerrno> #include <sys/socket.h> +#include <sys/select.h> namespace Mad { namespace Net { @@ -36,14 +37,16 @@ void ClientConnection::connect(const IPAddress &address) throw(ConnectionExcepti if(sock < 0) throw ConnectionException("socket()", std::strerror(errno)); - if(::connect(sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) - throw ConnectionException("connect()", std::strerror(errno)); - peer = new IPAddress(address); + if(::connect(sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) { + close(sock); + delete peer; + throw ConnectionException("connect()", std::strerror(errno)); + } + connected = true; - gnutls_anon_allocate_client_credentials(&anoncred); gnutls_init(&session, GNUTLS_CLIENT); gnutls_set_default_priority(session); @@ -69,15 +72,26 @@ void ClientConnection::disconnect() { shutdown(sock, SHUT_RDWR); close(sock); - sock = -1; gnutls_deinit(session); - gnutls_anon_free_client_credentials(anoncred); delete peer; connected = false; } +bool ClientConnection::dataPending() { + if(!connected) + return false; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + struct timeval timeout = {0, 0}; + + return (select(sock + 1, &fds, NULL, NULL, &timeout) == 1); +} + } } diff --git a/src/Net/ClientConnection.h b/src/Net/ClientConnection.h index e90b2db..72a0a92 100644 --- a/src/Net/ClientConnection.h +++ b/src/Net/ClientConnection.h @@ -43,15 +43,22 @@ class ClientConnection : public Connection { } public: - ClientConnection() : connected(false), peer(0), sock(-1), session(0) {} + ClientConnection() : connected(false) { + gnutls_anon_allocate_client_credentials(&anoncred); + } + virtual ~ClientConnection() { if(connected) disconnect(); + + gnutls_anon_free_client_credentials(anoncred); } void connect(const IPAddress &address) throw(ConnectionException); void disconnect(); + virtual bool dataPending(); + virtual bool isConnected() const {return connected;} virtual const IPAddress* getPeer() const {return peer;} }; diff --git a/src/Net/Connection.cpp b/src/Net/Connection.cpp index bc38ed2..49b51b4 100644 --- a/src/Net/Connection.cpp +++ b/src/Net/Connection.cpp @@ -55,7 +55,7 @@ bool Connection::recieve() { return false; while(true) { - if(!gnutls_record_check_pending(getSession())) + if(!dataPending()) return false; if(read < sizeof(Packet::Data)) { diff --git a/src/Net/Connection.h b/src/Net/Connection.h index 1879f9e..80b721f 100644 --- a/src/Net/Connection.h +++ b/src/Net/Connection.h @@ -46,6 +46,8 @@ class Connection { virtual bool isConnected() const = 0; virtual const IPAddress* getPeer() const = 0; + virtual bool dataPending() = 0; + bool send(const Packet &packet); bool recieve(); diff --git a/src/Net/Makefile.am b/src/Net/Makefile.am index b52b7b9..fc630ac 100644 --- a/src/Net/Makefile.am +++ b/src/Net/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp Connection.cpp Packet.cpp +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Packet.cpp -noinst_HEADERS = ClientConnection.h Connection.h Exception.h ConnectionException.h \ +noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h Exception.h ConnectionException.h \ InvalidAddressException.h IPAddress.h Packet.h diff --git a/src/Net/Makefile.in b/src/Net/Makefile.in index 0715d58..4e7923a 100644 --- a/src/Net/Makefile.in +++ b/src/Net/Makefile.in @@ -45,7 +45,8 @@ CONFIG_HEADER = $(top_builddir)/src/config.h CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnet_la_LIBADD = -am_libnet_la_OBJECTS = ClientConnection.lo Connection.lo Packet.lo +am_libnet_la_OBJECTS = ClientConnection.lo ServerConnection.lo \ + Connection.lo Packet.lo libnet_la_OBJECTS = $(am_libnet_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -178,8 +179,8 @@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp Connection.cpp Packet.cpp -noinst_HEADERS = ClientConnection.h Connection.h Exception.h ConnectionException.h \ +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Packet.cpp +noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h Exception.h ConnectionException.h \ InvalidAddressException.h IPAddress.h Packet.h all: all-am @@ -236,6 +237,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ClientConnection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Connection.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/Packet.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ServerConnection.Plo@am__quote@ .cpp.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/src/Net/ServerConnection.cpp b/src/Net/ServerConnection.cpp new file mode 100644 index 0000000..4a0bf15 --- /dev/null +++ b/src/Net/ServerConnection.cpp @@ -0,0 +1,145 @@ +/* + * ServerConnection.cpp + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#include "ServerConnection.h" +#include "IPAddress.h" +#include <cstring> +#include <cerrno> +#include <fstream> +#include <sys/socket.h> + +namespace Mad { +namespace Net { + +bool ServerConnection::loadDHParams(const std::string &file) { + std::ifstream stream(file.c_str()); + + if(!stream.is_open()) + return false; + + std::string data, line; + + while(!stream.eof()) { + std::getline(stream, line); + data += line + "\n"; + } + + stream.close(); + + gnutls_datum_t datum; + datum.data = new unsigned char[data.size()]; + datum.size = data.size(); + + std::memcpy(datum.data, data.data(), data.size()); + + int ret = gnutls_dh_params_import_pkcs3(dh_params, &datum, GNUTLS_X509_FMT_PEM); + + if(ret == 0) + gnutls_anon_set_server_dh_params(anoncred, dh_params); + + delete [] datum.data; + + return (ret == 0); +} + +bool ServerConnection::listen(const IPAddress &address) { + const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; + + if(connected) + disconnect(); + + int listen_sock = socket(PF_INET, SOCK_STREAM, 0); + if(listen_sock < 0) + return false; + + peer = new IPAddress(address); + + if(bind(listen_sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) { + close(listen_sock); + delete peer; + return false; + } + + if(::listen(listen_sock, 1024) < 0) { + close(listen_sock); + delete peer; + return false; + } + + sock = accept(listen_sock, NULL, NULL); + if(sock < 0) { + close(listen_sock); + delete peer; + return false; + } + + close(listen_sock); + + connected = true; + + gnutls_init(&session, GNUTLS_SERVER); + + gnutls_set_default_priority(session); + gnutls_kx_set_priority(session, kx_list); + + gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); + + gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(sock)); + + int ret = gnutls_handshake(session); + if(ret < 0) { + disconnect(); + + return false; + } + + return true; +} + +void ServerConnection::disconnect() { + if(!connected) + return; + + gnutls_bye(session, GNUTLS_SHUT_RDWR); + + shutdown(sock, SHUT_RDWR); + close(sock); + + gnutls_deinit(session); + + delete peer; + + connected = false; +} + +bool ServerConnection::dataPending() { + if(!connected) + return false; + + fd_set fds; + FD_ZERO(&fds); + FD_SET(sock, &fds); + + struct timeval timeout = {0, 0}; + + return (select(sock + 1, &fds, NULL, NULL, &timeout) == 1); +} + +} +} diff --git a/src/Net/ServerConnection.h b/src/Net/ServerConnection.h new file mode 100644 index 0000000..a1e839f --- /dev/null +++ b/src/Net/ServerConnection.h @@ -0,0 +1,72 @@ +/* + * ServerConnection.h + * + * Copyright (C) 2008 Matthias Schiffer <matthias@gamezock.de> + * + * 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 <http://www.gnu.org/licenses/>. + */ + +#ifndef MAD_NET_SERVERCONNECTION_H_ +#define MAD_NET_SERVERCONNECTION_H_ + +#include "Connection.h" +#include <string> + +namespace Mad { +namespace Net { + +class ServerConnection : public Connection { + private: + bool connected; + IPAddress *peer; + + int sock; + gnutls_session_t session; + gnutls_anon_server_credentials_t anoncred; + gnutls_dh_params_t dh_params; + + protected: + virtual gnutls_session_t& getSession() { + return session; + } + + public: + ServerConnection() : connected(false) { + gnutls_anon_allocate_server_credentials(&anoncred); + gnutls_dh_params_init(&dh_params); + } + + virtual ~ServerConnection() { + if(connected) + disconnect(); + + gnutls_dh_params_deinit(dh_params); + gnutls_anon_free_server_credentials(anoncred); + } + + bool loadDHParams(const std::string &file); + + bool listen(const IPAddress &address); + void disconnect(); + + virtual bool dataPending(); + + virtual bool isConnected() const {return connected;} + virtual const IPAddress* getPeer() const {return peer;} +}; + +} +} + +#endif /*MAD_NET_SERVERCONNECTION_H_*/ |