summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <matthias@gamezock.de>2008-06-26 00:45:12 +0200
committerMatthias Schiffer <matthias@gamezock.de>2008-06-26 00:45:12 +0200
commit27fe7a9e94704e7bd5420b0c3b59016943f0a333 (patch)
tree2565d419ec2c79f8d8b0860a3c11ab5b4824fa21
parent0e38acdaff7ef753f1d4e140eec9dbaec6f7a047 (diff)
downloadmad-27fe7a9e94704e7bd5420b0c3b59016943f0a333.tar
mad-27fe7a9e94704e7bd5420b0c3b59016943f0a333.zip
Neue Listener-Klasse
-rw-r--r--src/Net/ClientConnection.cpp1
-rw-r--r--src/Net/Listener.cpp102
-rw-r--r--src/Net/Listener.h52
-rw-r--r--src/Net/Makefile.am4
-rw-r--r--src/Net/Makefile.in7
-rw-r--r--src/Net/ServerConnection.cpp56
-rw-r--r--src/Net/ServerConnection.h18
-rw-r--r--src/mad-core.cpp27
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;