From fcab8098d6a9a385e0e5edfb26f4abf615da77ca Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 10 Oct 2008 15:04:28 +0200 Subject: FdManager hinzugef?gt und Verbindungsklassen angepasst --- src/Net/ClientConnection.cpp | 4 ++ src/Net/Connection.cpp | 29 +++++++++--- src/Net/Connection.h | 6 +-- src/Net/FdManager.cpp | 102 +++++++++++++++++++++++++++++++++++++++++++ src/Net/FdManager.h | 58 ++++++++++++++++++++++++ src/Net/Listener.cpp | 53 ++++++++-------------- src/Net/Listener.h | 7 ++- src/Net/Makefile.am | 4 +- src/Net/Makefile.in | 7 +-- src/Net/ServerConnection.cpp | 4 ++ 10 files changed, 220 insertions(+), 54 deletions(-) create mode 100644 src/Net/FdManager.cpp create mode 100644 src/Net/FdManager.h (limited to 'src/Net') diff --git a/src/Net/ClientConnection.cpp b/src/Net/ClientConnection.cpp index 5c602e1..25673fd 100644 --- a/src/Net/ClientConnection.cpp +++ b/src/Net/ClientConnection.cpp @@ -18,7 +18,9 @@ */ #include "ClientConnection.h" +#include "FdManager.h" #include "IPAddress.h" + #include #include #include @@ -96,6 +98,8 @@ void ClientConnection::connect(const IPAddress &address, bool daemon0) throw(Com gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)sock); + FdManager::getFdManager()->registerFd(sock, sigc::mem_fun(this, &Connection::sendReceive)); + handshake(); } diff --git a/src/Net/Connection.cpp b/src/Net/Connection.cpp index 03e9f73..72f9848 100644 --- a/src/Net/Connection.cpp +++ b/src/Net/Connection.cpp @@ -18,6 +18,7 @@ */ #include "Connection.h" +#include "FdManager.h" #include "IPAddress.h" #include #include @@ -67,8 +68,11 @@ void Connection::doHandshake() { int ret = gnutls_handshake(session); if(ret < 0) { - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) + if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + updateEvents(); return; + } + // TODO: Error doDisconnect(); @@ -85,8 +89,10 @@ void Connection::doBye() { int ret = gnutls_bye(session, GNUTLS_SHUT_RDWR); if(ret < 0) { - if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) + if(ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN) { + updateEvents(); return; + } // TODO: Error doDisconnect(); @@ -172,6 +178,8 @@ void Connection::doReceive() { delete [] data; } + + updateEvents(); } bool Connection::rawReceive(unsigned long length, @@ -188,6 +196,8 @@ bool Connection::rawReceive(unsigned long length, transR.transmitted = 0; transR.notify = notify; + updateEvents(); + return true; } @@ -215,6 +225,8 @@ void Connection::doSend() { transS.pop(); } } + + updateEvents(); } bool Connection::rawSend(const uint8_t *data, unsigned long length) { @@ -225,7 +237,8 @@ bool Connection::rawSend(const uint8_t *data, unsigned long length) { std::memcpy(trans.data, data, length); transS.push(trans); - doSend(); + updateEvents(); + doSend(); // TODO !!! return true; } @@ -276,6 +289,8 @@ void Connection::doDisconnect() { if(!isConnected()) return; + FdManager::getFdManager()->unregisterFd(sock); + shutdown(sock, SHUT_RDWR); close(sock); @@ -284,13 +299,13 @@ void Connection::doDisconnect() { state = DISCONNECTED; } -struct pollfd Connection::getPollfd() const { - struct pollfd fd = {sock, (receiveComplete() ? 0 : POLLIN) | (sendQueueEmpty() ? 0 : POLLOUT), 0}; +void Connection::updateEvents() const { + short events = (receiveComplete() ? 0 : POLLIN) | (sendQueueEmpty() ? 0 : POLLOUT); if(state == HANDSHAKE || state == BYE) - fd.events = ((gnutls_record_get_direction(session) == 0) ? POLLIN : POLLOUT); + events = ((gnutls_record_get_direction(session) == 0) ? POLLIN : POLLOUT); - return fd; + FdManager::getFdManager()->setFdEvents(sock, events); } } diff --git a/src/Net/Connection.h b/src/Net/Connection.h index 77b8cc4..0d7e6cf 100644 --- a/src/Net/Connection.h +++ b/src/Net/Connection.h @@ -74,6 +74,8 @@ class Connection { void bye(); + void updateEvents() const; + // Prevent shallow copy Connection(const Connection &o); Connection& operator=(const Connection &o); @@ -146,11 +148,9 @@ class Connection { void disconnect(); - struct pollfd getPollfd() const; - bool send(const Packet &packet); - void sendReceive(short events = POLLIN|POLLOUT); + void sendReceive(short events); bool sendQueueEmpty() const {return transS.empty();} diff --git a/src/Net/FdManager.cpp b/src/Net/FdManager.cpp new file mode 100644 index 0000000..aab634d --- /dev/null +++ b/src/Net/FdManager.cpp @@ -0,0 +1,102 @@ +/* + * FdManager.cpp + * + * 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 . + */ + +#include "FdManager.h" +#include + + +namespace Mad { +namespace Net { + +FdManager FdManager::fdManager; + + +FdManager::FdManager() { + // TODO Auto-generated constructor stub + +} + +FdManager::~FdManager() { + // TODO Auto-generated destructor stub +} + + +bool FdManager::registerFd(int fd, const sigc::slot &handler, short events) { + struct pollfd pollfd = {fd, events, 0}; + + pollfds.insert(std::make_pair(fd, pollfd)); + + return handlers.insert(std::make_pair(fd, handler)).second; +} + +bool FdManager::unregisterFd(int fd) { + pollfds.erase(fd); + return handlers.erase(fd); +} + +bool FdManager::setFdEvents(int fd, short events) { + std::map::iterator pollfd = pollfds.find(fd); + + if(pollfd == pollfds.end()) + return false; + + if(pollfd->second.events != events) { + pollfd->second.events = events; + interrupt(); + } + + return true; +} + +short FdManager::getFdEvents(int fd) const { + std::map::const_iterator pollfd = pollfds.find(fd); + + if(pollfd == pollfds.end()) + return -1; + + return pollfd->second.events; +} + +void FdManager::interrupt() { + // TODO Implement this. +} + +void FdManager::run() { + size_t count = pollfds.size(); + struct pollfd *fdarray = new struct pollfd[count]; + + std::map::iterator pollfd = pollfds.begin(); + + for(size_t n = 0; n < count; ++n) { + fdarray[n] = pollfd->second; + ++pollfd; + } + + if(poll(fdarray, count, -1) > 0) { + for(size_t n = 0; n < count; ++n) { + if(fdarray[n].revents) + handlers[fdarray[n].fd](fdarray[n].revents); + } + } + + delete [] fdarray; +} + +} +} diff --git a/src/Net/FdManager.h b/src/Net/FdManager.h new file mode 100644 index 0000000..f6a528f --- /dev/null +++ b/src/Net/FdManager.h @@ -0,0 +1,58 @@ +/* + * FdManager.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_FDMANAGER_H_ +#define MAD_NET_FDMANAGER_H_ + +#include +#include +#include + +namespace Mad { +namespace Net { + +class FdManager { + private: + static FdManager fdManager; + + std::map pollfds; + std::map > handlers; + + FdManager(); + + public: + virtual ~FdManager(); + + static FdManager *getFdManager() {return &fdManager;} + + bool registerFd(int fd, const sigc::slot &handler, short events = 0); + bool unregisterFd(int fd); + + bool setFdEvents(int fd, short events); + short getFdEvents(int fd) const; + + void interrupt(); + + void run(); +}; + +} +} + +#endif /* MAD_NET_FDMANAGER_H_ */ diff --git a/src/Net/Listener.cpp b/src/Net/Listener.cpp index 9233a79..ed820d0 100644 --- a/src/Net/Listener.cpp +++ b/src/Net/Listener.cpp @@ -18,7 +18,9 @@ */ #include "Listener.h" +#include "FdManager.h" #include "ServerConnection.h" + #include #include #include @@ -26,6 +28,19 @@ namespace Mad { namespace Net { +void Listener::acceptHandler(int) { + int sd; + struct sockaddr_in sa; + socklen_t addrlen = sizeof(sa); + + + while((sd = accept(sock, (struct sockaddr*)&sa, &addrlen)) >= 0) { + connections.push_back(new ServerConnection(sd, IPAddress(sa), dh_params, x905CertFile, x905KeyFile)); + + addrlen = sizeof(sa); + } +} + Listener::Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, const IPAddress &address0) throw(Common::Exception) : x905CertFile(x905CertFile0), x905KeyFile(x905KeyFile0), address(address0) { gnutls_dh_params_init(&dh_params); @@ -62,6 +77,8 @@ Listener::Listener(const std::string &x905CertFile0, const std::string &x905KeyF throw Common::Exception("listen()", Common::Exception::INTERNAL_ERRNO, errno); } + + FdManager::getFdManager()->registerFd(sock, sigc::mem_fun(this, &Listener::acceptHandler), POLLIN); } Listener::~Listener() { @@ -76,43 +93,9 @@ Listener::~Listener() { gnutls_dh_params_deinit(dh_params); } -std::vector Listener::getPollfds() const { - std::vector pollfds; - - struct pollfd fd = {sock, POLLIN, 0}; - pollfds.push_back(fd); - - for(std::list::const_iterator con = connections.begin(); con != connections.end(); ++con) - pollfds.push_back((*con)->getPollfd()); - - return pollfds; -} - -ServerConnection* Listener::getConnection(const std::map &pollfdMap) { +ServerConnection* Listener::getConnection() { // TODO: Logging - int sd; - struct sockaddr_in sa; - socklen_t addrlen = sizeof(sa); - - - while((sd = accept(sock, (struct sockaddr*)&sa, &addrlen)) >= 0) { - connections.push_back(new ServerConnection(sd, IPAddress(sa), dh_params, x905CertFile, x905KeyFile)); - - addrlen = sizeof(sa); - } - - for(std::list::iterator con = connections.begin(); con != connections.end(); ++con) { - std::map::const_iterator events = pollfdMap.find((*con)->getSocket()); - - if(events != pollfdMap.end()) { - if(*events->second) - (*con)->sendReceive(*events->second); - } - else - (*con)->sendReceive(); - } - for(std::list::iterator con = connections.begin(); con != connections.end();) { if(!(*con)->isConnected()) { delete *con; diff --git a/src/Net/Listener.h b/src/Net/Listener.h index 9c4ddab..a095439 100644 --- a/src/Net/Listener.h +++ b/src/Net/Listener.h @@ -24,7 +24,6 @@ #include #include -#include #include #include #include @@ -45,6 +44,8 @@ class Listener { std::list connections; + void acceptHandler(int); + // Prevent shallow copy Listener(const Listener &o); Listener& operator=(const Listener &o); @@ -53,9 +54,7 @@ class Listener { Listener(const std::string &x905CertFile0, const std::string &x905KeyFile0, const IPAddress &address0 = IPAddress()) throw(Common::Exception); virtual ~Listener(); - std::vector getPollfds() const; - - ServerConnection* getConnection(const std::map &pollfdMap); + ServerConnection* getConnection(); }; } diff --git a/src/Net/Makefile.am b/src/Net/Makefile.am index 84ef644..907b47c 100644 --- a/src/Net/Makefile.am +++ b/src/Net/Makefile.am @@ -1,7 +1,7 @@ SUBDIRS = Packets noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp IPAddress.cpp Listener.cpp Packet.cpp +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp FdManager.cpp IPAddress.cpp Listener.cpp Packet.cpp libnet_la_LIBADD = Packets/libpackets.la -noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h IPAddress.h Listener.h Packet.h +noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h FdManager.h IPAddress.h Listener.h Packet.h diff --git a/src/Net/Makefile.in b/src/Net/Makefile.in index a0eb761..6e9051f 100644 --- a/src/Net/Makefile.in +++ b/src/Net/Makefile.in @@ -49,7 +49,7 @@ CONFIG_CLEAN_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libnet_la_DEPENDENCIES = Packets/libpackets.la am_libnet_la_OBJECTS = ClientConnection.lo ServerConnection.lo \ - Connection.lo IPAddress.lo Listener.lo Packet.lo + Connection.lo FdManager.lo IPAddress.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 @@ -199,9 +199,9 @@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ SUBDIRS = Packets noinst_LTLIBRARIES = libnet.la -libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp IPAddress.cpp Listener.cpp Packet.cpp +libnet_la_SOURCES = ClientConnection.cpp ServerConnection.cpp Connection.cpp FdManager.cpp IPAddress.cpp Listener.cpp Packet.cpp libnet_la_LIBADD = Packets/libpackets.la -noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h IPAddress.h Listener.h Packet.h +noinst_HEADERS = ClientConnection.h ServerConnection.h Connection.h FdManager.h IPAddress.h Listener.h Packet.h all: all-recursive .SUFFIXES: @@ -255,6 +255,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)/FdManager.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/IPAddress.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@ diff --git a/src/Net/ServerConnection.cpp b/src/Net/ServerConnection.cpp index fbdd69f..05cc861 100644 --- a/src/Net/ServerConnection.cpp +++ b/src/Net/ServerConnection.cpp @@ -18,7 +18,9 @@ */ #include "ServerConnection.h" +#include "FdManager.h" #include "IPAddress.h" + #include #include #include @@ -71,6 +73,8 @@ ServerConnection::ServerConnection(int sock0, const IPAddress &address, gnutls_d gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); gnutls_transport_set_ptr(session, (gnutls_transport_ptr_t)sock); + FdManager::getFdManager()->registerFd(sock, sigc::mem_fun(this, &Connection::sendReceive)); + handshake(); } -- cgit v1.2.3