diff options
-rw-r--r-- | src/Net/ClientConnection.cpp | 1 | ||||
-rw-r--r-- | src/Net/Listener.cpp | 102 | ||||
-rw-r--r-- | src/Net/Listener.h | 52 | ||||
-rw-r--r-- | src/Net/Makefile.am | 4 | ||||
-rw-r--r-- | src/Net/Makefile.in | 7 | ||||
-rw-r--r-- | src/Net/ServerConnection.cpp | 56 | ||||
-rw-r--r-- | src/Net/ServerConnection.h | 18 | ||||
-rw-r--r-- | src/mad-core.cpp | 27 |
8 files changed, 193 insertions, 74 deletions
diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp index ca12f9f..7fdfd68 100644 --- a/src/Net/ClientConnection.cpp +++ b/src/Net/ClientConnection.cpp @@ -91,6 +91,7 @@ void ClientConnection::connect(const IPAddress &address, bool daemon0) throw(Con gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); + gnutls_transport_set_lowat(session, 0); gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(sock)); handshake(); diff --git a/src/Net/Listener.cpp b/src/Net/Listener.cpp new file mode 100644 index 0000000..b981b20 --- /dev/null +++ b/src/Net/Listener.cpp @@ -0,0 +1,102 @@ +/* + * Listener.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 "Listener.h" +#include "ServerConnection.h" +#include <cerrno> +#include <cstring> +#include <fcntl.h> + +#include <iostream> + +namespace Mad { +namespace Net { + +Listener::Listener(const IPAddress &address0) throw(ConnectionException) +: address(address0) { + gnutls_dh_params_init(&dh_params); + gnutls_dh_params_generate2(dh_params, 768); + + sock = socket(PF_INET, SOCK_STREAM, 0); + + if(sock < 0) + throw ConnectionException("socket()", std::strerror(errno)); + + // Set non-blocking flag + int flags = fcntl(sock, F_GETFL, 0); + + if(flags < 0) { + close(sock); + + throw ConnectionException("fcntl()", std::strerror(errno)); + } + + fcntl(sock, F_SETFL, flags | O_NONBLOCK); + + // Set reuse address + flags = 1; + setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &flags, sizeof(flags)); + + if(bind(sock, address.getSockAddr(), address.getSockAddrLength()) < 0) { + close(sock); + + throw ConnectionException("bind()", std::strerror(errno)); + } + + if(listen(sock, 64) < 0) { + close(sock); + + throw ConnectionException("listen()", std::strerror(errno)); + } +} + +Listener::~Listener() { + shutdown(sock, SHUT_RDWR); + close(sock); + + gnutls_dh_params_deinit(dh_params); +} + +ServerConnection* Listener::getConnection() { + int sd; + struct sockaddr_in sa; + socklen_t addrlen = sizeof(sa); + + while((sd = accept(sock, reinterpret_cast<struct sockaddr*>(&sa), &addrlen)) >= 0) { + connections.push_back(new ServerConnection(sd, IPAddress(sa), dh_params)); + + addrlen = sizeof(sa); + } + + for(std::list<ServerConnection*>::iterator con = connections.begin(); con != connections.end(); con++) { + (*con)->sendReceive(); + + if(!(*con)->isConnecting()) { + ServerConnection *connection = *con; + connections.erase(con); + + return connection; + } + } + + return 0; +} + +} +} diff --git a/src/Net/Listener.h b/src/Net/Listener.h new file mode 100644 index 0000000..0837fb0 --- /dev/null +++ b/src/Net/Listener.h @@ -0,0 +1,52 @@ +/* + * Listener.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_LISTENER_H_ +#define MAD_NET_LISTENER_H_ + +#include "IPAddress.h" +#include "ConnectionException.h" +#include <gnutls/gnutls.h> +#include <list> + +namespace Mad { +namespace Net { + +class ServerConnection; + +class Listener { + private: + IPAddress address; + int sock; + + gnutls_dh_params_t dh_params; + + std::list<ServerConnection*> connections; + + public: + Listener(const IPAddress &address0) throw(ConnectionException); + virtual ~Listener(); + + ServerConnection* getConnection(); +}; + +} +} + +#endif /*MAD_NET_LISTENER_H_*/ diff --git a/src/Net/Makefile.am b/src/Net/Makefile.am index fc630ac..8e49695 100644 --- a/src/Net/Makefile.am +++ b/src/Net/Makefile.am @@ -1,6 +1,6 @@ noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Packet.cpp +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Listener.cpp Packet.cpp noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h Exception.h ConnectionException.h \ - InvalidAddressException.h IPAddress.h Packet.h + InvalidAddressException.h IPAddress.h Listener.h Packet.h diff --git a/src/Net/Makefile.in b/src/Net/Makefile.in index 83b718d..e99597e 100644 --- a/src/Net/Makefile.in +++ b/src/Net/Makefile.in @@ -46,7 +46,7 @@ CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnet_la_LIBADD = am_libnet_la_OBJECTS = ClientConnection.lo ServerConnection.lo \ - Connection.lo Packet.lo + Connection.lo Listener.lo Packet.lo libnet_la_OBJECTS = $(am_libnet_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)/src depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -181,9 +181,9 @@ target_alias = @target_alias@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Packet.cpp +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp Listener.cpp Packet.cpp noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h Exception.h ConnectionException.h \ - InvalidAddressException.h IPAddress.h Packet.h + InvalidAddressException.h IPAddress.h Listener.h Packet.h all: all-am @@ -238,6 +238,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)/Listener.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@ diff --git a/src/Net/ServerConnection.cpp b/src/Net/ServerConnection.cpp index 4ad6215..4f1c78c 100644 --- a/src/Net/ServerConnection.cpp +++ b/src/Net/ServerConnection.cpp @@ -57,65 +57,27 @@ void ServerConnection::connectionHeaderReceiveHandler(const void *data, unsigned enterReceiveLoop(); } -void ServerConnection::listen(const IPAddress &address) throw(ConnectionException) { - const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; - - if(isConnected()) - disconnect(); - - int listen_sock = socket(PF_INET, SOCK_STREAM, 0); - if(listen_sock < 0) - throw ConnectionException("socket()", std::strerror(errno)); - - peer = new IPAddress(address); - - if(bind(listen_sock, peer->getSockAddr(), peer->getSockAddrLength()) < 0) { - close(listen_sock); - delete peer; - - throw ConnectionException("bind()", std::strerror(errno)); - } - - if(::listen(listen_sock, 1024) < 0) { - close(listen_sock); - delete peer; - - throw ConnectionException("listen()", std::strerror(errno)); - } +ServerConnection::ServerConnection(int sock0, const IPAddress &address, gnutls_dh_params_t dh_params) +: daemon(false) { + sock = sock0; - struct sockaddr_in sa; - socklen_t addrlen = sizeof(sa); + gnutls_anon_allocate_server_credentials(&anoncred); - sock = accept(listen_sock, reinterpret_cast<struct sockaddr*>(&sa), &addrlen); - if(sock < 0) { - close(listen_sock); - delete peer; - - throw ConnectionException("accept()", std::strerror(errno)); - } - close(listen_sock); + gnutls_anon_set_server_dh_params(anoncred, dh_params); - // Set non-blocking flag - int flags = fcntl(sock, F_GETFL, 0); - - if(flags < 0) { - close(sock); - - throw ConnectionException("fcntl()", std::strerror(errno)); - } - - fcntl(sock, F_SETFL, flags | O_NONBLOCK); - - *peer = IPAddress(address); + peer = new IPAddress(address); gnutls_init(&session, GNUTLS_SERVER); gnutls_set_default_priority(session); + + const int kx_list[] = {GNUTLS_KX_ANON_DH, 0}; gnutls_kx_set_priority(session, kx_list); gnutls_credentials_set(session, GNUTLS_CRD_ANON, anoncred); + gnutls_transport_set_lowat(session, 0); gnutls_transport_set_ptr(session, reinterpret_cast<gnutls_transport_ptr_t>(sock)); handshake(); diff --git a/src/Net/ServerConnection.h b/src/Net/ServerConnection.h index 0fd5f0b..ff88ad3 100644 --- a/src/Net/ServerConnection.h +++ b/src/Net/ServerConnection.h @@ -27,38 +27,32 @@ namespace Mad { namespace Net { +class Listener; + class ServerConnection : public Connection { + friend class Listener; + private: IPAddress *peer; bool daemon; gnutls_anon_server_credentials_t anoncred; - gnutls_dh_params_t dh_params; void connectionHeaderReceiveHandler(const void *data, unsigned long length); protected: + ServerConnection(int sock0, const IPAddress &address, gnutls_dh_params_t dh_params); + virtual void connectionHeader() { rawReceive(sizeof(ConnectionHeader), sigc::mem_fun(this, &ServerConnection::connectionHeaderReceiveHandler)); } public: - ServerConnection() : daemon(false) { - gnutls_anon_allocate_server_credentials(&anoncred); - - gnutls_dh_params_init(&dh_params); - gnutls_dh_params_generate2(dh_params, 768); - gnutls_anon_set_server_dh_params(anoncred, dh_params); - } - virtual ~ServerConnection() { - gnutls_dh_params_deinit(dh_params); gnutls_anon_free_server_credentials(anoncred); } - void listen(const IPAddress &address) throw(ConnectionException); - bool isDaemonConnection() const {return daemon;} }; diff --git a/src/mad-core.cpp b/src/mad-core.cpp index 830f26a..3ef7a80 100644 --- a/src/mad-core.cpp +++ b/src/mad-core.cpp @@ -17,6 +17,7 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "Net/Listener.h" #include "Net/ServerConnection.h" #include "Net/IPAddress.h" #include <iostream> @@ -27,7 +28,7 @@ bool running = true; void receiveHandler(const Mad::Net::Connection*, const Mad::Net::Packet &packet) { std::cout << "Received packet:" << std::endl; std::cout << " Type: " << packet.getType() << std::endl; - std::cout << " Request ID: " << packet.getRequestId() << std::endl; + std::cout << " Request ID: 0x" << std::hex << std::uppercase << packet.getRequestId() << std::dec << std::endl; std::cout << " Length: " << packet.getLength() << std::endl; running = false; @@ -35,21 +36,27 @@ void receiveHandler(const Mad::Net::Connection*, const Mad::Net::Packet &packet) int main() { Mad::Net::Connection::init(); - - Mad::Net::ServerConnection connection; - - connection.signalReceive().connect(sigc::ptr_fun(receiveHandler)); - try { - connection.listen(Mad::Net::IPAddress("0.0.0.0", 6666)); - while(running) connection.sendReceive(); + try { + Mad::Net::Listener listener(Mad::Net::IPAddress("0.0.0.0", 6666)); + + Mad::Net::ServerConnection *connection = 0; + + while((connection = listener.getConnection()) == 0) + usleep(100000); + + connection->signalReceive().connect(sigc::ptr_fun(receiveHandler)); + + while(running) + connection->sendReceive(); + + connection->disconnect(); + delete connection; } catch(Mad::Net::Exception &e) { std::cerr << "Connection error: " << e.what() << std::endl; } - connection.disconnect(); - Mad::Net::Connection::deinit(); return 0; |