浏览代码

use SO_REUSEADDR socket option for servers to reduce waiting time for os to free a port after a server exited unexpectedly

Kolja Strohm 1 年之前
父节点
当前提交
462df09450
共有 2 个文件被更改,包括 582 次插入528 次删除
  1. 414 394
      Network/Server.cpp
  2. 168 134
      Network/Server.h

+ 414 - 394
Network/Server.cpp

@@ -1,56 +1,70 @@
-#include <openssl/ssl.h>
-#include <openssl/err.h>
 #include "Server.h"
+
+#include <openssl/err.h>
+#include <openssl/ssl.h>
 #ifndef WIN32
-#include <string.h>
+#    include <string.h>
 #endif
+#include <iostream>
 #include <Key.h>
 #include <Text.h>
-#include <iostream>
 
 using namespace Network;
 
 // Inhalt der Server Klasse aus Server.h
-// Konstruktor 
+// Konstruktor
 Server::Server()
-	: ReferenceCounter()
+    : ReferenceCounter()
 {
-	sock = 0;
-	memset(&addresse, 0, sizeof(addresse)); // Adresse setzen
-	addresse.sin_family = AF_INET;
-	addresse.sin_addr.s_addr = ADDR_ANY;
-	klients = 0;
+    sock = 0;
+    memset(&addresse, 0, sizeof(addresse)); // Adresse setzen
+    addresse.sin_family = AF_INET;
+    addresse.sin_addr.s_addr = ADDR_ANY;
+    klients = 0;
 }
 
-// Destruktor 
+// Destruktor
 Server::~Server()
 {
-	trenne();
+    trenne();
 }
 
-// nicht constant 
-bool Server::verbinde(unsigned short port, int warteschlangenLen) // Öffnet das Socket
+// nicht constant
+bool Server::verbinde(
+    unsigned short port, int warteschlangenLen) // Öffnet das Socket
 {
-	sock = socket(AF_INET, SOCK_STREAM, 0); // Socket erstellen
-	addresse.sin_port = htons(port); // port setzen
-	if (bind(sock, (struct sockaddr*)&addresse, sizeof(addresse)) == -1) // socket öffnen
-	{
-		trenne();
-		return 0; // Fehler
-	}
-	if (listen(sock, warteschlangenLen) == -1) // Klients annehmen
-	{
-		trenne();
-		return 0; // Fehler
-	}
-	return 1;
+    sock = socket(AF_INET, SOCK_STREAM, 0); // Socket erstellen
+    addresse.sin_port = htons(port);        // port setzen
+    if (sock < 0)
+    {
+        sock = 0;
+        return 0;
+    }
+#ifdef WIN32
+    char reuseSocket = 1;
+    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(char));
+#else
+    int reuseSocket = 1;
+    setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(int));
+#endif
+    if (bind(sock, (struct sockaddr*)&addresse, sizeof(addresse))
+        == -1) // socket öffnen
+    {
+        trenne();
+        return 0; // Fehler
+    }
+    if (listen(sock, warteschlangenLen) == -1) // Klients annehmen
+    {
+        trenne();
+        return 0; // Fehler
+    }
+    return 1;
 }
 
 SKlient* Server::getKlient() // nimmt Klient an
 {
-	if (!sock)
-		return 0;
-	sockaddr_in client;
+    if (!sock) return 0;
+    sockaddr_in client;
     int len = sizeof(addresse);
     fd_set set;
     int rv = 0;
@@ -66,281 +80,280 @@ SKlient* Server::getKlient() // nimmt Klient an
     }
     if (!sock) return 0;
 #ifdef WIN32
-	SOCKET cls = accept(sock, (sockaddr*)&client, &len); // Klient empfangen
-	if (cls == INVALID_SOCKET)
-	{
-		trenne();
-		return 0;
-	}
+    SOCKET cls = accept(sock, (sockaddr*)&client, &len); // Klient empfangen
+    if (cls == INVALID_SOCKET)
+    {
+        trenne();
+        return 0;
+    }
 #else
-	SOCKET cls = accept(sock, (sockaddr*)&client, (socklen_t*)&len); // Klient empfangen
-	if (!cls)
-	{
-		if (errno == ECONNABORTED || errno == EBADF)
-			trenne();
-		return 0;
-	}
+    SOCKET cls = accept(
+        sock, (sockaddr*)&client, (socklen_t*)&len); // Klient empfangen
+    if (!cls)
+    {
+        if (errno == ECONNABORTED || errno == EBADF) trenne();
+        return 0;
+    }
 #endif
-	client.sin_port = addresse.sin_port;
-	klients++;
-	return new SKlient(client, cls); // Klient Handle Klasse zurückgeben
+    client.sin_port = addresse.sin_port;
+    klients++;
+    return new SKlient(client, cls); // Klient Handle Klasse zurückgeben
 }
 
 int Server::getKlients(bool reset) // gibt die Anzahl der Klients zurück
 {
-	int ret = klients;
-	if (reset)
-		klients = 0;
-	return ret;
+    int ret = klients;
+    if (reset) klients = 0;
+    return ret;
 }
 
 bool Server::trenne() // beendet den Server
 {
-	if (!sock)
-		return 1;
-	if (closesocket(sock) < 0) // socket schließen
-		return 0;
-	sock = 0;
-	return 1;
+    if (!sock) return 1;
+    if (closesocket(sock) < 0) // socket schließen
+        return 0;
+    sock = 0;
+    return 1;
 }
 
 // constant
 unsigned short Server::getPort() const // gibt den Port zurück
 {
-	return htons(addresse.sin_port);
+    return htons(addresse.sin_port);
 }
 
-bool Server::isConnected() const // giebt 1 zurück, falls der Server verbunden ist
+bool Server::isConnected()
+    const // giebt 1 zurück, falls der Server verbunden ist
 {
-	return sock != 0;
+    return sock != 0;
 }
 
 // Inhalt der SKlient Klasse aus Server.h
-// Konstruktor 
+// Konstruktor
 SKlient::SKlient(sockaddr_in addresse, SOCKET sock)
-	: ReferenceCounter()
+    : ReferenceCounter()
 {
-	clientAddr = addresse;
-	this->sock = sock;
-	downStreamBytes = 0;
-	upStreamBytes = 0;
-	sendeKey = 0;
-	empfangKey = 0;
+    clientAddr = addresse;
+    this->sock = sock;
+    downStreamBytes = 0;
+    upStreamBytes = 0;
+    sendeKey = 0;
+    empfangKey = 0;
 }
 
-// Destruktor 
+// Destruktor
 SKlient::~SKlient()
 {
-	trenne();
-	if (sendeKey)
-		sendeKey->release();
-	if (empfangKey)
-		empfangKey->release();
+    trenne();
+    if (sendeKey) sendeKey->release();
+    if (empfangKey) empfangKey->release();
 }
 
-// nicht constant 
-void SKlient::setEmpfangTimeout(int miliseconds) // Setzt ein timeout fürs empfangen von daten
+// nicht constant
+void SKlient::setEmpfangTimeout(
+    int miliseconds) // Setzt ein timeout fürs empfangen von daten
 {
 #ifdef WIN32
-	DWORD timeout = miliseconds;
-	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
+    DWORD timeout = miliseconds;
+    setsockopt(
+        sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
 #else
-	struct timeval tv;
-	tv.tv_sec = miliseconds / 1000;
-	tv.tv_usec = (miliseconds % 1000) * 1000;
-	setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+    struct timeval tv;
+    tv.tv_sec = miliseconds / 1000;
+    tv.tv_usec = (miliseconds % 1000) * 1000;
+    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
 #endif
 }
 
 void SKlient::setSendeKeyZ(Encryption::Key* key) // Setzt den Key fürs Senden
 {
-	if (sendeKey)
-		sendeKey->release();
-	sendeKey = key;
+    if (sendeKey) sendeKey->release();
+    sendeKey = key;
 }
 
-void SKlient::setEmpfangKeyZ(Encryption::Key* key) // Setzt den Key fürs Empfangen
+void SKlient::setEmpfangKeyZ(
+    Encryption::Key* key) // Setzt den Key fürs Empfangen
 {
-	if (empfangKey)
-		empfangKey->release();
-	empfangKey = key;
+    if (empfangKey) empfangKey->release();
+    empfangKey = key;
 }
 
 void SKlient::setSendeKey(const char* key, int len) // Setzt den Key fürs Senden
 {
-	if (!sendeKey)
-		sendeKey = new Encryption::Key();
-	sendeKey->setKey(key, len);
+    if (!sendeKey) sendeKey = new Encryption::Key();
+    sendeKey->setKey(key, len);
 }
 
-void SKlient::setEmpfangKey(const char* key, int len) // Setzt den Key fürs Empfangen
+void SKlient::setEmpfangKey(
+    const char* key, int len) // Setzt den Key fürs Empfangen
 {
-	if (!empfangKey)
-		empfangKey = new Encryption::Key();
-	empfangKey->setKey(key, len);
+    if (!empfangKey) empfangKey = new Encryption::Key();
+    empfangKey->setKey(key, len);
 }
 
 bool SKlient::sende(const char* nachricht, int len) // sendet zum Klient
 {
-	if (!sock)
-		return 0;
-	int ll = 0;
-	while (len > 0)
-	{
+    if (!sock) return 0;
+    int ll = 0;
+    while (len > 0)
+    {
 #ifdef WIN32
-		int l = send(sock, nachricht + ll, len, 0);
+        int l = send(sock, nachricht + ll, len, 0);
 #else
-		int l = (int)send(sock, nachricht + ll, len, MSG_NOSIGNAL);
+        int l = (int)send(sock, nachricht + ll, len, MSG_NOSIGNAL);
 #endif
-		if (l <= 0)
-			return 0; // Fehler
-		len -= l;
-		ll += l;
-	}
-	upStreamBytes += ll;
-	return 1;
-}
-
-bool SKlient::getNachricht(char* nachricht, int len) // empfängt Nachricht von Klient
-{
-	if (!sock)
-		return 0;
-	int ll = 0;
-	while (len > 0)
-	{
-		int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL);
-		if (l <= 0)
-			return 0; // Fehler
-		len -= l;
-		ll += l;
-	}
-	downStreamBytes += ll;
-	return 1;
-}
-
-bool SKlient::sendeEncrypted(const char* nachricht, int len) // sendet zum Server
-{
-	if (!sendeKey)
-		return sende(nachricht, len);
-	Encryption::Bytes* n = new Encryption::Bytes(nachricht, len);
-	sendeKey->codieren(dynamic_cast<Encryption::Bytes*>(n->getThis())); int ll = 0;
-	while (len > 0)
-	{
+        if (l <= 0) return 0; // Fehler
+        len -= l;
+        ll += l;
+    }
+    upStreamBytes += ll;
+    return 1;
+}
+
+bool SKlient::getNachricht(
+    char* nachricht, int len) // empfängt Nachricht von Klient
+{
+    if (!sock) return 0;
+    int ll = 0;
+    while (len > 0)
+    {
+        int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL);
+        if (l <= 0) return 0; // Fehler
+        len -= l;
+        ll += l;
+    }
+    downStreamBytes += ll;
+    return 1;
+}
+
+bool SKlient::sendeEncrypted(
+    const char* nachricht, int len) // sendet zum Server
+{
+    if (!sendeKey) return sende(nachricht, len);
+    Encryption::Bytes* n = new Encryption::Bytes(nachricht, len);
+    sendeKey->codieren(dynamic_cast<Encryption::Bytes*>(n->getThis()));
+    int ll = 0;
+    while (len > 0)
+    {
 #ifdef WIN32
-		int l = send(sock, n->getBytes() + ll, len, 0);
+        int l = send(sock, n->getBytes() + ll, len, 0);
 #else
-		int l = (int)send(sock, n->getBytes() + ll, len, MSG_NOSIGNAL);
+        int l = (int)send(sock, n->getBytes() + ll, len, MSG_NOSIGNAL);
 #endif
-		if (l <= 0)
-		{
-			n->release();
-			return 0; // Fehler
-		}
-		len -= l;
-		ll += l;
-	}
-	upStreamBytes += ll;
-	n->release();
-	return 1;
-}
-
-bool SKlient::getNachrichtEncrypted(char* nachricht, int len) // empfängt Nachricht
-{
-	if (!empfangKey)
-		return getNachricht(nachricht, len);
-	int ll = 0;
-	while (len > 0)
-	{
-		int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL);
-		if (l <= 0)
-			return 0; // Fehler
-		len -= l;
-		ll += l;
-	}
-	Encryption::Bytes* n = new Encryption::Bytes();
-	n->setBytesZ(nachricht, ll);
-	empfangKey->decodieren(n);
-	downStreamBytes += ll;
-	return 1;
-}
-
-int SKlient::getDownloadBytes(bool reset) // gibt die anzahl von empfangen bytes zurück
-{
-	int ret = downStreamBytes;
-	if (reset)
-		downStreamBytes = 0;
-	return ret;
-}
-
-int SKlient::getUploadBytes(bool reset) // gibt die anzahl von versendeter bytes zurück
-{
-	int ret = upStreamBytes;
-	if (reset)
-		upStreamBytes = 0;
-	return ret;
+        if (l <= 0)
+        {
+            n->release();
+            return 0; // Fehler
+        }
+        len -= l;
+        ll += l;
+    }
+    upStreamBytes += ll;
+    n->release();
+    return 1;
+}
+
+bool SKlient::getNachrichtEncrypted(
+    char* nachricht, int len) // empfängt Nachricht
+{
+    if (!empfangKey) return getNachricht(nachricht, len);
+    int ll = 0;
+    while (len > 0)
+    {
+        int l = (int)recv(sock, nachricht + ll, len, MSG_WAITALL);
+        if (l <= 0) return 0; // Fehler
+        len -= l;
+        ll += l;
+    }
+    Encryption::Bytes* n = new Encryption::Bytes();
+    n->setBytesZ(nachricht, ll);
+    empfangKey->decodieren(n);
+    downStreamBytes += ll;
+    return 1;
+}
+
+int SKlient::getDownloadBytes(
+    bool reset) // gibt die anzahl von empfangen bytes zurück
+{
+    int ret = downStreamBytes;
+    if (reset) downStreamBytes = 0;
+    return ret;
+}
+
+int SKlient::getUploadBytes(
+    bool reset) // gibt die anzahl von versendeter bytes zurück
+{
+    int ret = upStreamBytes;
+    if (reset) upStreamBytes = 0;
+    return ret;
 }
 
 bool SKlient::trenne() // trennt die Verbindung zum Klient
 {
-	if (!sock)
-		return 0;
-	if (closesocket(sock) < 0) // trennen
-		return 0;
-	sock = 0;
-	return 1;
+    if (!sock) return 0;
+    if (closesocket(sock) < 0) // trennen
+        return 0;
+    sock = 0;
+    return 1;
 }
 
-// constant 
-bool SKlient::hatNachricht(int zeit) const // Wartet eine Zeit Lang auf eine Nachricht
+// constant
+bool SKlient::hatNachricht(
+    int zeit) const // Wartet eine Zeit Lang auf eine Nachricht
 {
-	fd_set set;
-	FD_ZERO(&set);
-	FD_SET(sock, &set);
-	timeval time = { zeit / 1000, zeit };
-	return select(0, &set, 0, 0, &time) == 1;
+    fd_set set;
+    FD_ZERO(&set);
+    FD_SET(sock, &set);
+    timeval time = {zeit / 1000, zeit};
+    return select(0, &set, 0, 0, &time) == 1;
 }
 
 unsigned short SKlient::getPort() const // gibt den Port zurück
 {
-	return htons(clientAddr.sin_port);
+    return htons(clientAddr.sin_port);
 }
 
 const char* SKlient::getIp() const // gibt die Ip des Klients zurück
 {
-	return inet_ntoa(clientAddr.sin_addr);
+    return inet_ntoa(clientAddr.sin_addr);
 }
 
 int pem_passwd_cb(char* buf, int size, int rwflag, void* userdata)
 {
-	const char* passw = ((Text*)userdata)->getText();
-	memcpy(buf, passw, MIN((unsigned int)size, strlen(passw) + 1));
-	return (int)strlen(buf);
+    const char* passw = ((Text*)userdata)->getText();
+    memcpy(buf, passw, MIN((unsigned int)size, strlen(passw) + 1));
+    return (int)strlen(buf);
 }
 
 bool SSLErrorCheck(int result, SSL* ssl, const char* action)
 {
-	if (result <= 0)
-	{
-		std::cout << "ERROR: '" << action << "' returned error code: " << SSL_get_error(ssl, result) << "\n";
-		std::cout.flush();
-		return 0;
-	}
-	return 1;
+    if (result <= 0)
+    {
+        std::cout << "ERROR: '" << action
+                  << "' returned error code: " << SSL_get_error(ssl, result)
+                  << "\n";
+        std::cout.flush();
+        return 0;
+    }
+    return 1;
 }
 
 bool SSLErrorCheck(__int64 result, const char* action)
 {
-	if (result <= 0)
-	{
-		unsigned long error = ERR_get_error();
-		std::cout << "ERROR: '" << action << "' returned " << result << " error code: " << error << "(" << ERR_reason_error_string(error) << ")\n";
-		std::cout.flush();
-		return 0;
-	}
-	return 1;
+    if (result <= 0)
+    {
+        unsigned long error = ERR_get_error();
+        std::cout << "ERROR: '" << action << "' returned " << result
+                  << " error code: " << error << "("
+                  << ERR_reason_error_string(error) << ")\n";
+        std::cout.flush();
+        return 0;
+    }
+    return 1;
 }
 
-bool SKlient::waitForNextMessage() const // wartet bis es etwas zu empfangen gibt
+bool SKlient::waitForNextMessage()
+    const // wartet bis es etwas zu empfangen gibt
 {
     fd_set set;
     int rv = 0;
@@ -355,93 +368,104 @@ bool SKlient::waitForNextMessage() const // wartet bis es etwas zu empfangen gib
         if (rv == -1) return 0;
     }
     if (!sock) return 0;
-	char c;
-	int l = (int)recv(sock, &c, 1, MSG_WAITALL | MSG_PEEK);
-	if (l <= 0)
-		return 0; // Fehler
-	return 1;
+    char c;
+    int l = (int)recv(sock, &c, 1, MSG_WAITALL | MSG_PEEK);
+    if (l <= 0) return 0; // Fehler
+    return 1;
 }
 
-
 // Inhalt der SSLServer Klasse
-// Konstruktor 
+// Konstruktor
 SSLServer::SSLServer()
-	: ReferenceCounter()
-{
-	s = 0;
-	const SSL_METHOD* method = TLS_server_method();
-	ctx = SSL_CTX_new(method);
-	SSLErrorCheck(SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION), "SSL_CTX_set_min_proto_version");
-	SSLErrorCheck(SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION), "SSL_CTX_set_max_proto_version");
-	SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
-	SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
-	passw = new Text();
-	SSL_CTX_set_default_passwd_cb_userdata(ctx, passw);
-	addr.sin_family = AF_INET;
-	addr.sin_addr.s_addr = htonl(INADDR_ANY);
-	klients = 0;
-}
-
-// Destruktor 
+    : ReferenceCounter()
+{
+    s = 0;
+    const SSL_METHOD* method = TLS_server_method();
+    ctx = SSL_CTX_new(method);
+    SSLErrorCheck(SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION),
+        "SSL_CTX_set_min_proto_version");
+    SSLErrorCheck(SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION),
+        "SSL_CTX_set_max_proto_version");
+    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
+    SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
+    passw = new Text();
+    SSL_CTX_set_default_passwd_cb_userdata(ctx, passw);
+    addr.sin_family = AF_INET;
+    addr.sin_addr.s_addr = htonl(INADDR_ANY);
+    klients = 0;
+}
+
+// Destruktor
 SSLServer::~SSLServer()
 {
-	trenne();
-	SSL_CTX_free(ctx);
-	passw->release();
+    trenne();
+    SSL_CTX_free(ctx);
+    passw->release();
 #ifdef WIN32
-	OPENSSL_thread_stop();
+    OPENSSL_thread_stop();
 #endif
 }
 
-// nicht constant 
+// nicht constant
 // Setzt den Pfad zur Datei, in dem das Certifikat gespeichert ist
 bool SSLServer::setCertificateFile(const char* file)
 {
-	return SSLErrorCheck(SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM), "SSL_CTX_use_certificate_file");
+    return SSLErrorCheck(
+        SSL_CTX_use_certificate_file(ctx, file, SSL_FILETYPE_PEM),
+        "SSL_CTX_use_certificate_file");
 }
 
 // Setzt den Pfad zur Datei, in dem der private Schlüssel gespeichert ist
 bool SSLServer::setPrivateKeyFile(const char* file)
 {
-	return SSLErrorCheck(SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM), "SSL_CTX_use_PrivateKey_file");
+    return SSLErrorCheck(
+        SSL_CTX_use_PrivateKey_file(ctx, file, SSL_FILETYPE_PEM),
+        "SSL_CTX_use_PrivateKey_file");
 }
 
-// setzt das passwort des private keys (muss vor setPrivateKeyFile aufgerufen werden)
+// setzt das passwort des private keys (muss vor setPrivateKeyFile aufgerufen
+// werden)
 void SSLServer::setPrivateKeyPassword(const char* password)
 {
-	passw->setText(password);
+    passw->setText(password);
 }
 
 // Öffnet das Socket
 bool SSLServer::verbinde(unsigned short port, int warteschlangenLen)
 {
-	addr.sin_port = htons(port);
-	s = socket(AF_INET, SOCK_STREAM, 0);
-	if (s < 0)
-	{
-		s = 0;
-		return 0;
-	}
-	if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
-	{
-		trenne();
-		return 0;
-	}
-	if (listen(s, warteschlangenLen) < 0)
-	{
-		trenne();
-		return 0;
-	}
-	return 1;
+    addr.sin_port = htons(port);
+    s = socket(AF_INET, SOCK_STREAM, 0);
+    if (s < 0)
+    {
+        s = 0;
+        return 0;
+    }
+#ifdef WIN32
+    char reuseSocket = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(char));
+#else
+    int reuseSocket = 1;
+    setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reuseSocket, sizeof(int));
+#endif
+    if (bind(s, (struct sockaddr*)&addr, sizeof(addr)) < 0)
+    {
+        trenne();
+        return 0;
+    }
+    if (listen(s, warteschlangenLen) < 0)
+    {
+        trenne();
+        return 0;
+    }
+    return 1;
 }
 
 // nimmt Klient an
 SSLSKlient* SSLServer::getKlient()
 {
-	if (!s)
-		return 0;
-	int len = sizeof(addr);
-	struct sockaddr_in addr;
+    if (!s) return 0;
+    int len = sizeof(addr);
+    struct sockaddr_in addr;
     fd_set set;
     int rv = 0;
     struct timeval timeout;
@@ -456,191 +480,187 @@ SSLSKlient* SSLServer::getKlient()
     }
     if (!s) return 0;
 #ifdef WIN32
-	SOCKET client = accept(s, (struct sockaddr*)&addr, &len);
-	if (client == INVALID_SOCKET)
-	{
-		trenne();
-		return 0;
-	}
+    SOCKET client = accept(s, (struct sockaddr*)&addr, &len);
+    if (client == INVALID_SOCKET)
+    {
+        trenne();
+        return 0;
+    }
 #else
-	SOCKET client = accept(s, (sockaddr*)&addr, (socklen_t*)&len); // Klient empfangen
-	if (!client)
-	{
-		if (errno == ECONNABORTED || errno == EBADF)
-			trenne();
-		return 0;
-	}
+    SOCKET client
+        = accept(s, (sockaddr*)&addr, (socklen_t*)&len); // Klient empfangen
+    if (!client)
+    {
+        if (errno == ECONNABORTED || errno == EBADF) trenne();
+        return 0;
+    }
 #endif
-	addr.sin_port = this->addr.sin_port;
-	SSL* ssl = SSL_new(ctx);
-	if (ssl == 0 && !SSLErrorCheck(0, "SSL_new"))
-	{
-		closesocket(client);
-		return 0;
-	}
-	if (!SSLErrorCheck(SSL_set_fd(ssl, (int)client), ssl, "SSL_set_fd"))
-	{
-		SSL_free(ssl);
-		closesocket(client);
-		return 0;
-	}
-	if (!SSLErrorCheck(SSL_accept(ssl), ssl, "SSL_accept"))
-	{
-		SSL_free(ssl);
-		closesocket(client);
-		return 0;
-	}
-	klients++;
-	return new SSLSKlient(addr, ssl, client);
+    addr.sin_port = this->addr.sin_port;
+    SSL* ssl = SSL_new(ctx);
+    if (ssl == 0 && !SSLErrorCheck(0, "SSL_new"))
+    {
+        closesocket(client);
+        return 0;
+    }
+    if (!SSLErrorCheck(SSL_set_fd(ssl, (int)client), ssl, "SSL_set_fd"))
+    {
+        SSL_free(ssl);
+        closesocket(client);
+        return 0;
+    }
+    if (!SSLErrorCheck(SSL_accept(ssl), ssl, "SSL_accept"))
+    {
+        SSL_free(ssl);
+        closesocket(client);
+        return 0;
+    }
+    klients++;
+    return new SSLSKlient(addr, ssl, client);
 }
 
 // gibt die Anzahl der Klients zurück
 int SSLServer::getKlients(bool reset)
 {
-	int ret = klients;
-	if (reset)
-		klients = 0;
-	return ret;
+    int ret = klients;
+    if (reset) klients = 0;
+    return ret;
 }
 
 // beendet den Server
 bool SSLServer::trenne()
 {
-	if (!s)
-		return 1;
-	if (closesocket(s) < 0) // socket schließen
-		return 0;
-	s = 0;
-	return 1;
+    if (!s) return 1;
+    if (closesocket(s) < 0) // socket schließen
+        return 0;
+    s = 0;
+    return 1;
 }
 
 // constant
 // gibt den Port zurück
 unsigned short SSLServer::getPort() const
 {
-	return htons(addr.sin_port);
+    return htons(addr.sin_port);
 }
 
 // giebt 1 zurück, falls der Server verbunden ist
 bool SSLServer::isConnected() const
 {
-	return s != 0;
+    return s != 0;
 }
 
-
 // Inhalt der SSLSKlient Klasse
-// Konstruktor 
+// Konstruktor
 SSLSKlient::SSLSKlient(sockaddr_in client, SSL* ssl, SOCKET s)
-	: ReferenceCounter()
+    : ReferenceCounter()
 {
-	this->s = s;
-	clientAddr = client;
-	this->ssl = ssl;
-	downStreamBytes = 0;
-	upStreamBytes = 0;
+    this->s = s;
+    clientAddr = client;
+    this->ssl = ssl;
+    downStreamBytes = 0;
+    upStreamBytes = 0;
 }
 
-// Destruktor 
+// Destruktor
 SSLSKlient::~SSLSKlient()
 {
-	trenne();
+    trenne();
 #ifdef WIN32
-	OPENSSL_thread_stop();
+    OPENSSL_thread_stop();
 #endif
 }
 
-// nicht constant 
-void SSLSKlient::setEmpfangTimeout(int miliseconds) // Setzt ein timeout fürs empfangen von daten
+// nicht constant
+void SSLSKlient::setEmpfangTimeout(
+    int miliseconds) // Setzt ein timeout fürs empfangen von daten
 {
 #ifdef WIN32
-	DWORD timeout = miliseconds;
-	setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
+    DWORD timeout = miliseconds;
+    setsockopt(
+        s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof timeout);
 #else
-	struct timeval tv;
-	tv.tv_sec = miliseconds / 1000;
-	tv.tv_usec = (miliseconds % 1000) * 1000;
-	setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
+    struct timeval tv;
+    tv.tv_sec = miliseconds / 1000;
+    tv.tv_usec = (miliseconds % 1000) * 1000;
+    setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof tv);
 #endif
 }
 
 bool SSLSKlient::sende(const char* nachricht, int len) // sendet zum Klient
 {
-	if (!ssl)
-		return 0;
-	int ll = 0;
-	while (len > 0)
-	{
-		int l = SSL_write(ssl, nachricht + ll, len);
-		if (l <= 0)
-			return 0; // Fehler
-		len -= l;
-		ll += l;
-	}
-	upStreamBytes += ll;
-	return 1;
+    if (!ssl) return 0;
+    int ll = 0;
+    while (len > 0)
+    {
+        int l = SSL_write(ssl, nachricht + ll, len);
+        if (l <= 0) return 0; // Fehler
+        len -= l;
+        ll += l;
+    }
+    upStreamBytes += ll;
+    return 1;
 }
 
-bool SSLSKlient::getNachricht(char* nachricht, int len) // empfängt Nachricht von Klient
+bool SSLSKlient::getNachricht(
+    char* nachricht, int len) // empfängt Nachricht von Klient
 {
-	if (!ssl)
-		return 0;
-	int ll = 0;
-	while (len > 0)
-	{
-		int l = (int)SSL_read(ssl, nachricht + ll, len);
-		if (l <= 0)
-			return 0; // Fehler
-		len -= l;
-		ll += l;
-	}
-	downStreamBytes += ll;
-	return 1;
+    if (!ssl) return 0;
+    int ll = 0;
+    while (len > 0)
+    {
+        int l = (int)SSL_read(ssl, nachricht + ll, len);
+        if (l <= 0) return 0; // Fehler
+        len -= l;
+        ll += l;
+    }
+    downStreamBytes += ll;
+    return 1;
 }
 
-int SSLSKlient::getDownloadBytes(bool reset) // gibt die anzahl von empfangen bytes zurück
+int SSLSKlient::getDownloadBytes(
+    bool reset) // gibt die anzahl von empfangen bytes zurück
 {
-	int ret = downStreamBytes;
-	if (reset)
-		downStreamBytes = 0;
-	return ret;
+    int ret = downStreamBytes;
+    if (reset) downStreamBytes = 0;
+    return ret;
 }
 
-int SSLSKlient::getUploadBytes(bool reset) // gibt die anzahl von versendeter bytes zurück
+int SSLSKlient::getUploadBytes(
+    bool reset) // gibt die anzahl von versendeter bytes zurück
 {
-	int ret = upStreamBytes;
-	if (reset)
-		upStreamBytes = 0;
-	return ret;
+    int ret = upStreamBytes;
+    if (reset) upStreamBytes = 0;
+    return ret;
 }
 
 bool SSLSKlient::trenne() // trennt die Verbindung zum Klient
 {
-	if (!ssl)
-		return 0;
-	SSL_free(ssl);
-	if (closesocket(s) < 0) // trennen
-		return 0;
-	ssl = 0;
-	s = 0;
-	return 1;
+    if (!ssl) return 0;
+    SSL_free(ssl);
+    if (closesocket(s) < 0) // trennen
+        return 0;
+    ssl = 0;
+    s = 0;
+    return 1;
 }
 
-// constant 
-bool SSLSKlient::hatNachricht(int zeit) const // Wartet eine Zeit Lang auf eine Nachricht
+// constant
+bool SSLSKlient::hatNachricht(
+    int zeit) const // Wartet eine Zeit Lang auf eine Nachricht
 {
-	fd_set set;
-	FD_ZERO(&set);
-	FD_SET(SSL_get_rfd(ssl), &set);
-	timeval time = { zeit / 1000, zeit };
-	return SSL_pending(ssl) > 0 || select(0, &set, 0, 0, &time) == 1;
+    fd_set set;
+    FD_ZERO(&set);
+    FD_SET(SSL_get_rfd(ssl), &set);
+    timeval time = {zeit / 1000, zeit};
+    return SSL_pending(ssl) > 0 || select(0, &set, 0, 0, &time) == 1;
 }
 
 unsigned short SSLSKlient::getPort() const // gibt den Port zurück
 {
-	return htons(clientAddr.sin_port);
+    return htons(clientAddr.sin_port);
 }
 
 const char* SSLSKlient::getIp() const // gibt die Ip des Klients zurück
 {
-	return inet_ntoa(clientAddr.sin_addr);
+    return inet_ntoa(clientAddr.sin_addr);
 }

+ 168 - 134
Network/Server.h

@@ -1,151 +1,185 @@
 #ifndef Server_H
 #define Server_H
 
-#include "Network.h"
 #include <ReferenceCounter.h>
 
+#include "Network.h"
+
 #ifndef HEADER_OPENSSL_TYPES_H
-struct SSL_CTX;
-struct SSL;
+struct ssl_ctx_st;
+struct ssl_st;
 #endif
 
 namespace Framework
 {
-	namespace Encryption
-	{
-		class Key;
-	}
-	class Text;
-}
+    namespace Encryption
+    {
+        class Key;
+    }
+    class Text;
+} // namespace Framework
 
 using namespace Framework;
 
 namespace Network
 {
-	class Server; // aus dieser Datei
-	class SKlient; // aus dieser Datei
-
-	class Server : public virtual ReferenceCounter
-	{
-	private:
-		SOCKET sock;
-		SOCKADDR_IN addresse;
-		int klients;
-
-	public:
-		// Konstruktor 
-		__declspec(dllexport) Server();
-		// Destruktor 
-		__declspec(dllexport) ~Server();
-		// nicht constant 
-		__declspec(dllexport) bool verbinde(unsigned short port, int warteschlangenLen); // Öffnet das Socket
-		__declspec(dllexport) SKlient* getKlient(); // nimmt Klient an
-		__declspec(dllexport) int getKlients(bool reset); // gibt die Anzahl der Klients zurück
-		__declspec(dllexport) bool trenne(); // beendet den Server
-		// constant
-		__declspec(dllexport) unsigned short getPort() const; // gibt den Port zurück
-		__declspec(dllexport) bool isConnected() const; // giebt 1 zurück, falls der Server verbunden ist
-	};
-
-	class SKlient : public EncryptedVerbindung, public virtual ReferenceCounter
-	{
-	private:
-		SOCKET sock;
-		sockaddr_in clientAddr;
-		Encryption::Key* sendeKey;
-		Encryption::Key* empfangKey;
-		int downStreamBytes;
-		int upStreamBytes;
-
-	public:
-		// Konstruktor 
-		__declspec(dllexport) SKlient(sockaddr_in client, SOCKET sock);
-		// Destruktor 
-		__declspec(dllexport) ~SKlient();
-		// nicht constant 
-		__declspec(dllexport) void setEmpfangTimeout(int miliseconds); // Setzt ein timeout fürs empfangen von daten
-		__declspec(dllexport) void setSendeKeyZ(Encryption::Key* key); // Setzt den Schlüssel fürs Senden
-		__declspec(dllexport) void setEmpfangKeyZ(Encryption::Key* key); // Setzt den Schlüssel fürs Empfangen
-		__declspec(dllexport) void setSendeKey(const char* key, int len); // Setzt den Schlüssel fürs Senden
-		__declspec(dllexport) void setEmpfangKey(const char* key, int len); // Setzt den Schlüssel fürs Empfangen
-		__declspec(dllexport) bool sende(const char* nachricht, int len) override; // sendet zum Klient
-		__declspec(dllexport) bool getNachricht(char* nachricht, int len) override; // empfängt Nachricht von Klient
-		__declspec(dllexport) bool sendeEncrypted(const char* nachricht, int len) override; // sendet zum Server
-		__declspec(dllexport) bool getNachrichtEncrypted(char* nachricht, int len) override; // empfängt Nachricht
-		__declspec(dllexport) int getDownloadBytes(bool reset); // gibt die anzahl von empfangen bytes zurück
-		__declspec(dllexport) int getUploadBytes(bool reset); // gibt die anzahl von versendeter bytes zurück
-		__declspec(dllexport) bool trenne(); // trennt die Verbindung zum Klient
-		// constant 
-		__declspec(dllexport) bool hatNachricht(int zeit) const; // Wartet eine Zeit Lang auf eine Nachricht
-		__declspec(dllexport) unsigned short getPort() const; // gibt den Port zurück
-		__declspec(dllexport) const char* getIp() const; // gibt die Ip des Klients zurück
-		__declspec(dllexport) bool waitForNextMessage() const; // wartet bis es etwas zu empfangen gibt
-	};
-
-	class SSLSKlient;
-
-	class SSLServer : public virtual ReferenceCounter
-	{
-	private:
-		SOCKET s;
-		SOCKADDR_IN addr;
-		SSL_CTX* ctx;
-		Text* passw;
-		int klients;
-
-	public:
-		// Konstruktor 
-		__declspec(dllexport) SSLServer();
-		// Destruktor 
-		__declspec(dllexport) ~SSLServer();
-		// nicht constant 
-		// Setzt den Pfad zur Datei, in dem das Certifikat gespeichert ist
-		__declspec(dllexport) bool setCertificateFile(const char* file);
-		// Setzt den Pfad zur Datei, in dem der private Schlüssel gespeichert ist
-		__declspec(dllexport) bool setPrivateKeyFile(const char* file);
-		// setzt das passwort des private keys (muss vor setPrivateKeyFile aufgerufen werden)
-		__declspec(dllexport) void setPrivateKeyPassword(const char* password);
-		// Öffnet das Socket
-		__declspec(dllexport) bool verbinde(unsigned short port, int warteschlangenLen);
-		// nimmt Klient an
-		__declspec(dllexport) SSLSKlient* getKlient();
-		// gibt die Anzahl der Klients zurück
-		__declspec(dllexport) int getKlients(bool reset);
-		// beendet den Server
-		__declspec(dllexport) bool trenne();
-		// constant
-		// gibt den Port zurück
-		__declspec(dllexport) unsigned short getPort() const;
-		// giebt 1 zurück, falls der Server verbunden ist
-		__declspec(dllexport) bool isConnected() const;
-	};
-
-	class SSLSKlient : public Verbindung, public virtual ReferenceCounter
-	{
-	private:
-		SOCKET s;
-		SSL* ssl;
-		sockaddr_in clientAddr;
-		int downStreamBytes;
-		int upStreamBytes;
-
-	public:
-		// Konstruktor 
-		__declspec(dllexport) SSLSKlient(sockaddr_in client, SSL* ssl, SOCKET s);
-		// Destruktor 
-		__declspec(dllexport) ~SSLSKlient();
-		// nicht constant 
-		__declspec(dllexport) void setEmpfangTimeout(int miliseconds); // Setzt ein timeout fürs empfangen von daten
-		__declspec(dllexport) bool sende(const char* nachricht, int len) override; // sendet zum Klient
-		__declspec(dllexport) bool getNachricht(char* nachricht, int len) override; // empfängt Nachricht von Klient
-		__declspec(dllexport) int getDownloadBytes(bool reset); // gibt die anzahl von empfangen bytes zurück
-		__declspec(dllexport) int getUploadBytes(bool reset); // gibt die anzahl von versendeter bytes zurück
-		__declspec(dllexport) bool trenne(); // trennt die Verbindung zum Klient
-		// constant 
-		__declspec(dllexport) bool hatNachricht(int zeit) const; // Wartet eine Zeit Lang auf eine Nachricht
-		__declspec(dllexport) unsigned short getPort() const; // gibt den Port zurück
-		__declspec(dllexport) const char* getIp() const; // gibt die Ip des Klients zurück
-	};
-}
+    class Server;  // aus dieser Datei
+    class SKlient; // aus dieser Datei
+
+    class Server : public virtual ReferenceCounter
+    {
+    private:
+        SOCKET sock;
+        SOCKADDR_IN addresse;
+        int klients;
+
+    public:
+        // Konstruktor
+        __declspec(dllexport) Server();
+        // Destruktor
+        __declspec(dllexport) ~Server();
+        // nicht constant
+        __declspec(dllexport) bool verbinde(
+            unsigned short port, int warteschlangenLen); // Öffnet das Socket
+        __declspec(dllexport) SKlient* getKlient();      // nimmt Klient an
+        __declspec(dllexport) int getKlients(
+            bool reset); // gibt die Anzahl der Klients zurück
+        __declspec(dllexport) bool trenne(); // beendet den Server
+        // constant
+        __declspec(
+            dllexport) unsigned short getPort() const; // gibt den Port zurück
+        __declspec(dllexport) bool isConnected()
+            const; // giebt 1 zurück, falls der Server verbunden ist
+    };
+
+    class SKlient : public EncryptedVerbindung,
+                    public virtual ReferenceCounter
+    {
+    private:
+        SOCKET sock;
+        sockaddr_in clientAddr;
+        Encryption::Key* sendeKey;
+        Encryption::Key* empfangKey;
+        int downStreamBytes;
+        int upStreamBytes;
+
+    public:
+        // Konstruktor
+        __declspec(dllexport) SKlient(sockaddr_in client, SOCKET sock);
+        // Destruktor
+        __declspec(dllexport) ~SKlient();
+        // nicht constant
+        __declspec(dllexport) void setEmpfangTimeout(
+            int miliseconds); // Setzt ein timeout fürs empfangen von daten
+        __declspec(dllexport) void setSendeKeyZ(
+            Encryption::Key* key); // Setzt den Schlüssel fürs Senden
+        __declspec(dllexport) void setEmpfangKeyZ(
+            Encryption::Key* key); // Setzt den Schlüssel fürs Empfangen
+        __declspec(dllexport) void setSendeKey(
+            const char* key, int len); // Setzt den Schlüssel fürs Senden
+        __declspec(dllexport) void setEmpfangKey(
+            const char* key, int len); // Setzt den Schlüssel fürs Empfangen
+        __declspec(dllexport) bool sende(
+            const char* nachricht, int len) override; // sendet zum Klient
+        __declspec(dllexport) bool getNachricht(
+            char* nachricht, int len) override; // empfängt Nachricht von Klient
+        __declspec(dllexport) bool sendeEncrypted(
+            const char* nachricht, int len) override; // sendet zum Server
+        __declspec(dllexport) bool getNachrichtEncrypted(
+            char* nachricht, int len) override; // empfängt Nachricht
+        __declspec(dllexport) int getDownloadBytes(
+            bool reset); // gibt die anzahl von empfangen bytes zurück
+        __declspec(dllexport) int getUploadBytes(
+            bool reset); // gibt die anzahl von versendeter bytes zurück
+        __declspec(dllexport) bool trenne(); // trennt die Verbindung zum Klient
+        // constant
+        __declspec(dllexport) bool hatNachricht(
+            int zeit) const; // Wartet eine Zeit Lang auf eine Nachricht
+        __declspec(
+            dllexport) unsigned short getPort() const; // gibt den Port zurück
+        __declspec(dllexport) const
+            char* getIp() const; // gibt die Ip des Klients zurück
+        __declspec(dllexport) bool waitForNextMessage()
+            const; // wartet bis es etwas zu empfangen gibt
+    };
+
+    class SSLSKlient;
+
+    class SSLServer : public virtual ReferenceCounter
+    {
+    private:
+        SOCKET s;
+        SOCKADDR_IN addr;
+        ssl_ctx_st* ctx;
+        Text* passw;
+        int klients;
+
+    public:
+        // Konstruktor
+        __declspec(dllexport) SSLServer();
+        // Destruktor
+        __declspec(dllexport) ~SSLServer();
+        // nicht constant
+        // Setzt den Pfad zur Datei, in dem das Certifikat gespeichert ist
+        __declspec(dllexport) bool setCertificateFile(const char* file);
+        // Setzt den Pfad zur Datei, in dem der private Schlüssel gespeichert
+        // ist
+        __declspec(dllexport) bool setPrivateKeyFile(const char* file);
+        // setzt das passwort des private keys (muss vor setPrivateKeyFile
+        // aufgerufen werden)
+        __declspec(dllexport) void setPrivateKeyPassword(const char* password);
+        // Öffnet das Socket
+        __declspec(dllexport) bool verbinde(
+            unsigned short port, int warteschlangenLen);
+        // nimmt Klient an
+        __declspec(dllexport) SSLSKlient* getKlient();
+        // gibt die Anzahl der Klients zurück
+        __declspec(dllexport) int getKlients(bool reset);
+        // beendet den Server
+        __declspec(dllexport) bool trenne();
+        // constant
+        // gibt den Port zurück
+        __declspec(dllexport) unsigned short getPort() const;
+        // giebt 1 zurück, falls der Server verbunden ist
+        __declspec(dllexport) bool isConnected() const;
+    };
+
+    class SSLSKlient : public Verbindung,
+                       public virtual ReferenceCounter
+    {
+    private:
+        SOCKET s;
+        ssl_st* ssl;
+        sockaddr_in clientAddr;
+        int downStreamBytes;
+        int upStreamBytes;
+
+    public:
+        // Konstruktor
+        __declspec(dllexport)
+            SSLSKlient(sockaddr_in client, ssl_st* ssl, SOCKET s);
+        // Destruktor
+        __declspec(dllexport) ~SSLSKlient();
+        // nicht constant
+        __declspec(dllexport) void setEmpfangTimeout(
+            int miliseconds); // Setzt ein timeout fürs empfangen von daten
+        __declspec(dllexport) bool sende(
+            const char* nachricht, int len) override; // sendet zum Klient
+        __declspec(dllexport) bool getNachricht(
+            char* nachricht, int len) override; // empfängt Nachricht von Klient
+        __declspec(dllexport) int getDownloadBytes(
+            bool reset); // gibt die anzahl von empfangen bytes zurück
+        __declspec(dllexport) int getUploadBytes(
+            bool reset); // gibt die anzahl von versendeter bytes zurück
+        __declspec(dllexport) bool trenne(); // trennt die Verbindung zum Klient
+        // constant
+        __declspec(dllexport) bool hatNachricht(
+            int zeit) const; // Wartet eine Zeit Lang auf eine Nachricht
+        __declspec(
+            dllexport) unsigned short getPort() const; // gibt den Port zurück
+        __declspec(dllexport) const
+            char* getIp() const; // gibt die Ip des Klients zurück
+    };
+} // namespace Network
 
 #endif