123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423 |
- #include "WebSocket.h"
- #include "HttpRequest.h"
- #include <iostream>
- using namespace Network;
- using namespace WebSocket;
- using namespace Framework;
- __declspec( dllexport ) Frame &Frame::operator+=( const Frame &b ) // baut frames zusammen welche zu einer nachricht gehören
- {
- fin = b.fin;
- if( opcode == 0 )
- opcode = b.opcode;
- dataLength += b.dataLength;
- if( dataLength )
- {
- char *data = new char[ (int)dataLength ];
- if( data )
- memcpy( data, this->data, (int)(dataLength - b.dataLength) );
- if( b.data )
- memcpy( data + dataLength, b.data, (int)b.dataLength );
- delete[] this->data;
- this->data = data;
- }
- else
- {
- delete[] this->data;
- this->data = 0;
- }
- return *this;
- }
- __declspec( dllexport ) WebSocketClient::WebSocketClient( const char *path, const char *host, unsigned short port )
- : Thread()
- {
- queue = new Array< Frame >();
- callback = 0;
- klient = 0;
- this->path = path;
- this->host = host;
- this->port = port;
- lastPingFrame = 0;
- nextClose = 0;
- }
- WebSocketClient::~WebSocketClient()
- {
- disconnect();
- while( queue->getEintragAnzahl() )
- {
- Frame f = queue->get( 0 );
- delete[] f.data;
- queue->remove( 0 );
- }
- queue->release();
- }
- __declspec( dllexport ) void WebSocketClient::setMessageCallback( std::function< void( WebSocketClient *, __int64 size, const char *data, DataType typ ) > callback )
- {
- this->callback = callback;
- }
- __declspec( dllexport ) bool WebSocketClient::connect()
- {
- char allowedKeyChars[] = { 'a', 'b','c','d','e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
- 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
- '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
- 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 0 };
- __int64 numKeyChars = strlen( allowedKeyChars );
- if( !klient )
- {
- Text message = "GET ";
- message += path;
- message += " HTTP/1.1\r\n";
- message += "Host: ";
- message += host;
- message += "\r\nUpgrade: websocket\r\n";
- message += "Connection: Upgrade\r\n";
- char *key = new char[ 25 ];
- key[ 24 ] = 0;
- key[ 23 ] = '=';
- key[ 22 ] = '=';
- for( int i = 0; i < 22; i++ )
- key[ i ] = allowedKeyChars[ (int)( gen.rand() * numKeyChars ) ];
- message += "Sec-WebSocket-Key: ";
- message += key;
- delete[] key;
- message += "\r\nSec-WebSocket-Version: 13\r\n\r\n";
- klient = new Klient();
- if( !klient->verbinde( port, host ) )
- {
- klient = klient->release();
- return 0;
- }
- klient->sende( message, message.getLength() );
- Text answer;
- int br = 0;
- do
- {
- char buff[ 2 ];
- buff[ 1 ] = 0;
- if( klient->getNachricht( buff, 1 ) )
- answer += buff;
- else
- break;
- if( buff[ 0 ] == '\n' )
- br++;
- else if( buff[ 0 ] != '\r' )
- br = 0;
- } while( br < 2 && klient->hatNachricht( 1000 ) );
- HTTP::Answer *handshakeResponse = new HTTP::Answer( answer );
- if( handshakeResponse->getStatusCode() != 101 )
- {
- handshakeResponse->release();
- klient = klient->release();
- return 0;
- }
- handshakeResponse->release();
- start();
- return 1;
- }
- else
- return 1;
- }
- __declspec( dllexport ) bool WebSocketClient::send( __int64 size, const char *data, DataType typ )
- {
- Frame f;
- f.fin = 1;
- f.rsv1 = 0;
- f.rsv2 = 0;
- f.rsv3 = 0;
- f.mask = 1;
- if( typ == TEXT )
- f.opcode = 1;
- else
- f.opcode = 2;
- f.dataLength = size;
- f.data = new char[ (int)f.dataLength ];
- memcpy( f.data, data, (int)f.dataLength );
- f.key[ 0 ] = (unsigned char)(gen.rand() * 256);
- f.key[ 1 ] = (unsigned char)(gen.rand() * 256);
- f.key[ 2 ] = (unsigned char)(gen.rand() * 256);
- f.key[ 3 ] = (unsigned char)(gen.rand() * 256);
- c.lock();
- queue->add( f );
- c.unlock();
- return 1;
- }
- __declspec( dllexport ) void WebSocketClient::thread()
- {
- while( klient )
- {
- c2.lock();
- if( !klient )
- {
- c2.unlock();
- return;
- }
- if( klient->hatNachricht( 100 ) )
- {
- bool ok = 1;
- c2.unlock();
- bool first = 1;
- Frame m;
- unsigned char byte;
- do
- {
- c2.lock();
- if( !klient )
- {
- c2.unlock();
- return;
- }
- Frame message;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.fin = ( byte & 0x80 ) != 0;
- message.rsv1 = ( byte & 0x40 ) != 0;
- message.rsv2 = ( byte & 0x20 ) != 0;
- message.rsv3 = ( byte & 0x10 ) != 0;
- message.opcode = byte & 0xF;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.mask = ( byte & 0x80 ) != 0;
- message.dataLength = byte & 0x7F;
- if( message.dataLength == 126 )
- {
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength = byte << 8;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= byte;
- }
- else if( message.dataLength == 127 )
- {
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength = (__int64)byte << 56;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 48;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 40;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 32;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 24;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 16;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte << 8;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.dataLength |= (__int64)byte;
- }
- if( message.mask )
- {
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.key[ 0 ] = byte;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.key[ 1 ] = byte;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.key[ 2 ] = byte;
- ok &= klient->getNachricht( (char*)&byte, 1 );
- message.key[ 3 ] = byte;
- }
- if( !ok )
- message.dataLength = 1;
- message.data = 0;
- if( message.dataLength )
- message.data = new char[ (int)message.dataLength ];
- for( int i = 0; i < message.dataLength; i++ )
- {
- ok &= klient->getNachricht( (char*)&byte, 1 );
- if( message.mask )
- message.data[ i ] = byte ^ message.key[ i % 4 ];
- else
- message.data[ i ] = byte;
- }
- c2.unlock();
- if( first )
- m = message;
- else
- {
- m += message;
- delete[] message.data;
- }
- first = 0;
- if( !ok )
- break;
- } while( !m.fin );
- if( !ok )
- {
- delete[] m.data;
- return;
- }
- if( m.opcode == 0x9 )
- {
- m.opcode = 0xA;
- m.key[ 0 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 1 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 2 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 3 ] = (unsigned char)( gen.rand() * 256 );
- queue->add( m );
- }
- else if( m.opcode == 0xA )
- {
- delete[] m.data;
- }
- else if( m.opcode == 0x8 )
- {
- if( nextClose )
- {
- delete[] m.data;
- c2.lock();
- klient->trenne();
- klient = klient->release();
- c2.unlock();
- return;
- }
- else
- {
- m.key[ 0 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 1 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 2 ] = (unsigned char)( gen.rand() * 256 );
- m.key[ 3 ] = (unsigned char)( gen.rand() * 256 );
- queue->add( m );
- nextClose = 1;
- }
- }
- else if( callback )
- {
- callback( this, m.dataLength, m.data, m.opcode == 1 ? TEXT : BINARY );
- delete[] m.data;
- }
- }
- else
- {
- c2.unlock();
- c.lock();
- while( queue->getEintragAnzahl() )
- {
- Frame f = queue->get( 0 );
- c.unlock();
- unsigned char byte = ( f.fin ? 1 : 0 ) << 7;
- byte |= ( f.rsv1 ? 1 : 0 ) << 6;
- byte |= ( f.rsv2 ? 1 : 0 ) << 5;
- byte |= ( f.rsv3 ? 1 : 0 ) << 4;
- byte |= f.opcode & 0xF;
- c2.lock();
- if( !klient )
- {
- c2.unlock();
- return;
- }
- klient->sende( (char*)&byte, 1 );
- byte = ( f.mask ? 1 : 0 ) << 7;
- if( f.dataLength < 126 )
- byte |= (unsigned char)f.dataLength & 0x7F;
- else if( f.dataLength <= 32767 )
- byte |= 126;
- else
- byte |= 127;
- klient->sende( (char*)&byte, 1 );
- if( f.dataLength >= 126 )
- {
- if( f.dataLength <= 32767 )
- {
- byte = (unsigned char)( f.dataLength >> 8 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)f.dataLength & 0xFF;
- klient->sende( (char*)&byte, 1 );
- }
- else
- {
- byte = (unsigned char)( f.dataLength >> 56 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 48 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 40 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 32 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 24 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 16 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)( f.dataLength >> 8 );
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)f.dataLength & 0xFF;
- klient->sende( (char*)&byte, 1 );
- }
- }
- if( f.mask )
- {
- byte = (unsigned char)f.key[ 0 ];
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)f.key[ 1 ];
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)f.key[ 2 ];
- klient->sende( (char*)&byte, 1 );
- byte = (unsigned char)f.key[ 3 ];
- klient->sende( (char*)&byte, 1 );
- }
- if( f.dataLength )
- {
- for( int i = 0; i < f.dataLength; i++ )
- {
- if( f.mask )
- byte = (unsigned char)f.data[ i ] ^ f.key[ i % 4 ];
- else
- byte = (unsigned char)f.data[ i ];
- klient->sende( (char*)&byte, 1 );
- }
- }
- c2.unlock();
- delete[] f.data;
- c.lock();
- queue->remove( 0 );
- if( f.opcode == 0x8 )
- {
- if( nextClose )
- {
- c.unlock();
- c2.lock();
- klient->trenne();
- klient = klient->release();
- c2.unlock();
- return;
- }
- else
- {
- nextClose = 1;
- }
- }
- }
- c.unlock();
- }
- }
- }
- __declspec( dllexport ) void WebSocketClient::disconnect()
- {
- if( !klient )
- return;
- c2.lock();
- klient->trenne();
- klient = klient->release();
- c2.unlock();
- warteAufThread( 1000 );
- }
- __declspec( dllexport ) bool WebSocketClient::isConnected() const
- {
- return klient != 0;
- }
- // löscht das objekt wenn es nicht mehr gebraucht wird und beendet den Thread
- Thread *WebSocketClient::release()
- {
- #ifdef WIN32
- if( ref == 2 && run )
- disconnect();
- #endif
- return Thread::release();
- }
|