#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( char *key, int len ) // Setzt den Key fürs Senden { if( !sendeKey ) sendeKey = new Encryption::Key(); sendeKey->setKey( key, len ); } void Klient::setEmpfangKey( 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 ); } // 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(); }