#include #include #include "Klient.h" #ifndef WIN32 #include #include #include #endif #include #include using namespace Network; // inhalt der Klient Klasse aus Klient.h // Konstruktor Klient::Klient() : ReferenceCounter() { memset(&server, 0, sizeof(server)); server.sin_family = AF_INET; downStreamBytes = 0; upStreamBytes = 0; sock = 0; sendeKey = 0; empfangKey = 0; } // Destruktoe Klient::~Klient() { if (sock) trenne(); if (sendeKey) sendeKey->release(); if (empfangKey) empfangKey->release(); } // nicht constant void Klient::setSendeKeyZ(Encryption::Key* key) // Setzt den Key fürs Senden { if (sendeKey) sendeKey->release(); sendeKey = key; } void Klient::setEmpfangKeyZ(Encryption::Key* key) // Setzt den Key fürs Empfangen { if (empfangKey) empfangKey->release(); empfangKey = key; } void Klient::setSendeKey(const char* key, int len) // Setzt den Key fürs Senden { if (!sendeKey) sendeKey = new Encryption::Key(); sendeKey->setKey(key, len); } void Klient::setEmpfangKey(const char* key, int len) // Setzt den Key fürs Empfangen { if (!empfangKey) empfangKey = new Encryption::Key(); empfangKey->setKey(key, len); } bool Klient::verbinde(unsigned short port, const char* ip) // verbindet mit Server { if (sendeKey) sendeKey->setPos(0); if (empfangKey) empfangKey->setPos(0); if (sock) closesocket(sock); sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); long sIp = inet_addr(ip); // ip addresse if (sIp == INADDR_NONE) { struct hostent* pHostInfo = gethostbyname(ip); if (pHostInfo == 0) return 0; sIp = *(long*)pHostInfo->h_addr_list[0]; } memcpy((char*)&server.sin_addr, &sIp, sizeof(sIp)); server.sin_port = htons(port); // port if (connect(sock, (struct sockaddr*)&server, sizeof(server)) < 0) // verbinden return 0; // Fehler return 1; } bool Klient::sende(const char* nachricht, int len) // sendet zum Server { int ll = 0; while (len > 0) { #ifdef WIN32 int l = send(sock, nachricht + ll, len, 0); #else 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 Klient::getNachricht(char* nachricht, int len) // empfängt Nachricht { 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 Klient::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(n->getThis())); int ll = 0; while (len > 0) { #ifdef WIN32 int l = send(sock, n->getBytes() + ll, len, 0); #else 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 Klient::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 Klient::getDownloadBytes(bool reset) // gibt die anzahl von empfangen bytes zurück { int ret = downStreamBytes; if (reset) downStreamBytes = 0; return ret; } int Klient::getUploadBytes(bool reset) // gibt die anzahl von versendeter bytes zurück { int ret = upStreamBytes; if (reset) upStreamBytes = 0; return ret; } bool Klient::trenne() // Trennt die Verbindung zum Server { if (!sock) return 1; if (sendeKey) sendeKey->setPos(0); if (empfangKey) empfangKey->setPos(0); if (closesocket(sock) < 0) // verbindung Trennen return 0; // Fehler sock = 0; return 1; } // constant bool Klient::hatNachricht(int zeit) // 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; } unsigned short Klient::getServerPort() const // gibt den Port zurück { return htons(server.sin_port); } const char* Klient::getServerIp() const // gibt die Ip zurück { return inet_ntoa(server.sin_addr); } bool Klient::waitForNextMessage() const // wartet bis es etwas zu empfangen gibt { char c; int l = (int)recv(sock, &c, 1, MSG_WAITALL | MSG_PEEK); if (l <= 0) return 0; // Fehler return 1; } // Inhalt der SSLKlient Klasse aus Klient.h // Konstruktor SSLKlient::SSLKlient() : ReferenceCounter() { ctx = SSL_CTX_new(TLS_client_method()); SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION); SSL_CTX_set_max_proto_version(ctx, TLS1_3_VERSION); ip = 0; port = 0; bio = BIO_new_ssl_connect(ctx); BIO_get_ssl(bio, &ssl); downStreamBytes = 0; upStreamBytes = 0; connected = 0; } // Destruktor SSLKlient::~SSLKlient() { if (this->ip) this->ip->release(); if (connected) trenne(); BIO_free_all(bio); SSL_CTX_free(ctx); #ifdef WIN32 OPENSSL_thread_stop(); #endif } bool SSLKlient::verbinde(unsigned short port, const char* ip) // verbindet mit Server { this->port = port; if (this->ip) this->ip->release(); this->ip = new Text(ip); Text adr = ip; adr += ":"; adr += port; BIO_set_conn_hostname(bio, adr); connected = BIO_do_connect(bio) > 0; if (connected && BIO_do_handshake(bio) <= 0) trenne(); return connected; } bool SSLKlient::sende(const char* nachricht, int len) // sendet zum Server { 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 SSLKlient::getNachricht(char* nachricht, int len) // empfängt Nachricht { if (!connected) return 0; int ll = 0; while (len > 0) { int l = SSL_read(ssl, nachricht + ll, len); if (l <= 0) return 0; // Fehler len -= l; ll += l; } downStreamBytes += ll; return 1; } int SSLKlient::getDownloadBytes(bool reset) // gibt die anzahl von empfangen bytes zurück { int ret = downStreamBytes; if (reset) downStreamBytes = 0; return ret; } int SSLKlient::getUploadBytes(bool reset) // gibt die anzahl von versendeter bytes zurück { int ret = upStreamBytes; if (reset) upStreamBytes = 0; return ret; } bool SSLKlient::trenne() // Trennt die Verbindung zum Server { BIO_ssl_shutdown(bio); connected = 0; return 1; } // constant bool SSLKlient::hatNachricht(int zeit) // 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; } unsigned short SSLKlient::getServerPort() const // gibt den Port des Servers zurück { return port; } const char* SSLKlient::getServerIp() const // gibt die Ip des Servers zurück { return ip->getText(); }