summaryrefslogtreecommitdiffstats
path: root/src/Net
diff options
context:
space:
mode:
Diffstat (limited to 'src/Net')
-rw-r--r--src/Net/ClientConnection.cpp26
-rw-r--r--src/Net/ClientConnection.h9
-rw-r--r--src/Net/Connection.cpp2
-rw-r--r--src/Net/Connection.h2
-rw-r--r--src/Net/Makefile.am4
-rw-r--r--src/Net/Makefile.in8
-rw-r--r--src/Net/ServerConnection.cpp145
-rw-r--r--src/Net/ServerConnection.h72
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_*/