//**************************************************************************** //Copyright (C) 2005-2006 Beijing BlueDJ Technology Co.,Ltd. All rights reserved. //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 2 //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 (in the file LICENSE.GPL); if not, write to the Free Software //Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. //Please visit http://www.bluedj.com for more infomation about us. //Contact us at ggwizard@gmail.com or darkdong@gmail.com. //****************************************************************************/ #include "DJSocket.h" #include "DJHallController.h" #include "DJGameItem.h" #include "DJProgressDialog.h" #include "DJContact.h" #include "DJHallInterface.h" #include "HallUtility.h" #include "GameInterface.h" #include "protocol.h" #include "Utility.h" #include "DJMessageBox.h" #include "DJBaseGlobal.h" static const int KeepOnLine = 60000;//60 sec static const int DJGameProtocolLength = 5; static const char SpeedPackage[DJGameProtocolLength] = {0x05,DJGAME_PROTOCOL_TYPE_SPEED,0,0,0}; static const char KeepOnLinePackage[DJGameProtocolLength] = {0x05,DJGAME_PROTOCOL_TYPE_ACL,0,0,0}; static QString hallResDir = ":/HallRes"; bool socks4ConnectCallback( const QByteArray& buf, DJSocket* socket ) { Q_UNUSED(socket); djDebug() << "socks4ConnectCallback"; if ( buf.size() >= 8 ) { const Socks4Reply *reply = reinterpret_cast(buf.data()); if( 0 != reply->vn || 90 != reply->cd ) { QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("socks4 proxy connect failed!"),QMessageBox::Ok); return false; } } return true; } bool socks5VersionCallback( const QByteArray& buf, DJSocket* socket ) { djDebug() << "socks5VersionCallback"; if ( buf.size() == 2 ) { djDebug() << "==="; const Socks5VersionReply *reply= reinterpret_cast(buf.data()); if( 5 != reply->ver || ( 0 != reply->method && 2 != reply->method) ) { QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("socks5 proxy version error!"),QMessageBox::Ok); return false; }else { djDebug() << "version ok" << reply->method; if ( 0 == reply->method ) { //no auth need djDebug() << "no need auth"; socket->socks5RequestConnect(); }else { //need auth djDebug() << "need auth"; QString username,password; GetSettingProxyAuth( username,password ); socket->socks5RequestAuth( username, password ); } } return true; }else { QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("socks5 proxy version length error!"),QMessageBox::Ok); return false; } } bool socks5AuthCallback( const QByteArray& buf, DJSocket* socket ) { djDebug() << "socks5AuthCallback"; if ( buf.size() == 2 ) { const Socks5AuthReply *reply= reinterpret_cast(buf.data()); if( 1 != reply->ver || 0 != reply->status ) { djDebug() << "auth fail"; QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("socks5 proxy auth failed!"),QMessageBox::Ok); return false; }else { socket->socks5RequestConnect(); } return true; }else { return false; } } bool socks5ConnectCallback( const QByteArray& buf, DJSocket* socket ) { Q_UNUSED(socket); djDebug() << "socks5ConnectCallback"; if ( buf.size() >= 10 ) { const Socks5ConnectReply *reply= reinterpret_cast(buf.data()); if( 5 != reply->ver || 0 != reply->rep ) { QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("socks5 proxy connect failed!"),QMessageBox::Ok); return false; } } return true; } bool httpConnectCallback( const QByteArray& buf, DJSocket* socket ) { djDebug() << "httpConnectCallback"; djDebug() << socket->peerAddress().toString() << socket->peerPort(); QString string( buf ); djDebug() << string; //if ( buf.contains("HTTP/1.0 200 Connection established") ) if ( buf.contains("200 Connection established") ) return true; else { QMessageBox::information( 0,DJSocket::tr("network error"),DJSocket::tr("http proxy connect failed!"),QMessageBox::Ok); return false; } } DJSocket::DJSocket( Type type, DJHallController *hallController, QObject *parent ) :QTcpSocket(parent),m_socketType(type),m_hallController(hallController) { djDebug() << "DJSocket constructor" << m_socketType; m_lastRequestId = 0; m_port = 0; m_progressDlg = new DJProgressDialog( this, m_hallController->mainWindow() ); //m_progressDlg = new DJProgressDialog( this ); connect(this, SIGNAL( hostFound() ), SLOT( socketHostFound()) ); connect(this, SIGNAL( connected() ), SLOT( socketConnected()) ); connect(this, SIGNAL( disconnected() ), SLOT( socketDisconnected()) ); connect(this, SIGNAL( error(QAbstractSocket::SocketError)), SLOT(socketError(QAbstractSocket::SocketError))); connect(this, SIGNAL( readyRead()), SLOT(socketReadyRead()) ); connect(this, SIGNAL( bytesWritten(qint64)), SLOT(socketBytesWritten(qint64))); startTimer(KeepOnLine); } DJSocket::~DJSocket() { djDebug() << "DJSocket destructor"; clear(); //delete m_progressDlg; //m_progressDlg = 0; } void DJSocket::description() const { djDebug() << "DJSocket::description"; } void DJSocket::allGamesReloadSettings() { allGamesCommand( GAME_COMMAND_RELOAD_SETTING, QVariant() ); } void DJSocket::allGamesContactUserTypeChanged( quint32 userId, int contactUserType ) { QList list; list << QVariant(userId) << QVariant(contactUserType); QVariant parameters(list); allGamesCommand( GAME_COMMAND_CONTACT_USER_TYPE_CHANGED, parameters ); } void DJSocket::allGamesReconnect() { djDebug() << "allGamesReconnect"<curServerId() )//game has been closed return; //DJGameServerItem *serverItem = (DJGameServerItem*)gameItem->childItem( gameItem->curServerId() ); //if ( !serverItem ) //return; m_hallController->requestRelogin( gameItem, this, m_ip, m_port ); //allGamesCommand( GAME_COMMAND_RECONNECTING, QVariant() ); */ foreach( DJGameGameItem *gameItem, m_gameItems ) { if ( 0 == gameItem->curServerId() )//game has been closed continue; QVariant state = gameItem->gameControllerCommand( GAME_COMMAND_STATE, QVariant() ); if ( state.isValid() ) { bool isConnected = state.toBool(); djDebug()<<"isConnected"<requestRelogin( gameItem, this ); } } } } void DJSocket::connectToServer( const QString& ip, quint16 port, bool showProgress, const QString& text, int seconds ) { djDebug() << "connectToServer"; m_ip = ip; m_port = port; QString targetIp = ip; quint16 targetPort = port; m_proxyType = -1; do { if ( !GetSettingUseProxy() ) break; m_proxyType = GetSettingProxyType(); if ( -1 == m_proxyType ) break; QList data = GetSettingProxy( m_proxyType ).toList(); targetIp = data.at(0).toString(); targetPort = data.at(1).toString().toUInt(); djDebug() << "targetIp = " << targetIp << "targetPort = " << targetPort; }while(false); djDebug() << "ip=" << ip << "targetIp=" << targetIp << "port=" << port << "targetPort=" << targetPort; #if QT_VERSION < 0x040100 && defined( Q_WS_WIN ) djDebug() << "QT_VERSION < 4.1.0"; QHostInfo info = QHostInfo::fromName(targetIp); if ( !info.addresses().isEmpty() ) { QHostAddress address = info.addresses().first(); djDebug() << "address =" << address.toString(); connectToHost( address, targetPort ); if ( showProgress ) m_progressDlg->startProgress( seconds, text ); }else { QMessageBox::information( 0,tr("DNS failed"),tr("Can't resolve host name: ")+ip,QMessageBox::Ok); } #else djDebug() << "QT_VERSION >= 4.1.0"; connectToHost( targetIp, targetPort ); if ( showProgress ) m_progressDlg->startProgress( seconds, text ); #endif } void DJSocket::timeout() { djDebug() << "DJSocket::timeout"; abort(); clear(); //save the last server //SetSettingLastServer( QString(), 0 ); QMessageBox::information( 0,tr("Timeout"),tr("Can't connect to game server"),QMessageBox::Ok); } void DJSocket::cancel() { djDebug() << "DJSocket::cancel"; abort(); clear(); //save the last server //SetSettingLastServer( QString(), 0 ); } void DJSocket::stopProgress() { djDebug() << "DJSocket::stopProgress"; m_progressDlg->stopProgress(); } void DJSocket::socketHostFound() { djDebug() << "socketHostFound"; } void DJSocket::socketConnected() { djDebug() << "socketConnected" << "proxyType =" << m_proxyType; switch(m_proxyType) { case 0: connectToSocks5Proxy(); break; case 1: connectToSocks4Proxy(); break; case 2: connectToHttpProxy(); break; default: break; } } void DJSocket::socketDisconnected() { djDebug() << "socketDisconnected" << state(); if ( Hall == m_socketType ) { clear(); }else { stopProgress(); m_buf.clear(); m_requests.clear(); allGamesCommand( GAME_COMMAND_DISCONNECTED, QVariant() ); } } void DJSocket::socketError(QAbstractSocket::SocketError socketError) { djDebug() << "socketError" << "errorcode" << socketError << errorString() << "state" << state(); if ( Hall == m_socketType ) { clear(); DJMessageBox::information( 10, 0,tr("Socket Error"),QAbstractSocket::tr(errorString()), QMessageBox::Ok); }else { stopProgress(); m_buf.clear(); m_requests.clear(); } if ( QAbstractSocket::UnconnectedState == state() ) socketDisconnected(); else abort(); //DJMessageBox::information( 10, 0,tr("Socket Error"),QAbstractSocket::tr(errorString()), QMessageBox::Ok); //save the last server SetSettingLastServer( QString(), 0 ); } void DJSocket::socketReadyRead() { while ( bytesAvailable() || m_buf.size() ) { djDebug() << "socketReadyRead " << "bytesAvailable=" << bytesAvailable() << "m_buf size=" << m_buf.size(); //djDebug() << "before append data address = " << (void*)m_buf.data(); m_buf.append( readAll() ); //djDebug() << "after append data address = " << (void*)m_buf.data(); if ( !m_proxyCallbacks.isEmpty() ) { ProxyCallback proxyCallback = m_proxyCallbacks.takeFirst(); if ( !proxyCallback( m_buf, this ) ) { djDebug() << "proxy fail"; abort(); }else { djDebug() << "proxy ok"; } m_buf.clear(); } if ( m_buf.size() < DJGameProtocolLength ) { break; } const DJGameProtocol *protocol = reinterpret_cast(m_buf.data()); quint8 len = protocol->chTotalLen; if ( m_buf.size() < len ) { break; } DebugBuffer( m_buf, len ); switch( protocol->chType ) { case DJGAME_PROTOCOL_TYPE_ACL: aclHandler(m_buf); break; case DJGAME_PROTOCOL_TYPE_GAMELIST: { const GameDescritpor *gameDes = reinterpret_cast(protocol->chBuf); quint16 gameId = makeword(gameDes->chGameClass, gameDes->chGame); QString gameName = QString::fromUtf8(gameDes->szGameName); m_hallController->addGameItem( gameId, gameName ); break; } case DJGAME_PROTOCOL_TYPE_SERVERLIST2: { const ServerDescritpor2 *serverDes = reinterpret_cast(protocol->chBuf); quint16 gameId = makeword(serverDes->chGameClass, serverDes->chGame); quint16 serverId = letoh2( &serverDes->chServerID ); QString ip; if(IP_LENGTH == 6) ip = QString("%1.%2.%3.%4.%5.%6").arg(serverDes->chIP[0]).arg(serverDes->chIP[1]).arg(serverDes->chIP[2]) .arg(serverDes->chIP[3]).arg(serverDes->chIP[4]).arg(serverDes->chIP[5]); else ip = QString("%1.%2.%3.%4").arg(serverDes->chIP[0]).arg(serverDes->chIP[1]) .arg(serverDes->chIP[2]).arg(serverDes->chIP[3]); quint16 port = letoh2( &serverDes->chPort ); QString serverName = QString::fromUtf8( serverDes->szServerName ); int numberOfPlayers = letoh4( serverDes->uiPlayers ); m_hallController->addServerItem( gameId, serverId, ip, port, serverName, numberOfPlayers ); break; } case DJGAME_PROTOCOL_TYPE_GAMEDATA: { const GameDataHead *gameDataHead = reinterpret_cast( protocol->chBuf ); quint16 gameId = makeword(gameDataHead->chGameClass, gameDataHead->chGame); if( m_gameItems.contains( gameId ) ) { DJGameGameItem *gameItem = m_gameItems.value( gameId ); gameItem->gameControllerCommand( GAME_COMMAND_GAME_DATA, m_buf ); }else { djDebug() << "new game data" << gameId; //quint16 existingGameId = m_gameItems.constBegin().key(); DJGameGameItem *existingGameItem = m_gameItems.constBegin().value(); //QString userName,password; //existingGameItem->getLoginNamePass( userName, password ); quint16 serverId = existingGameItem->curServerId(); DJGameServerItem* existingServerItem = static_cast(existingGameItem->childItem(serverId)); DJGameClassItem *gameClassItem = 0; DJGameGameItem *gameItem = 0; DJGameServerItem *serverItem = 0; m_hallController->locateTreeItem( gameId>>8, gameId, 0, gameClassItem, gameItem, serverItem ); if ( gameItem ) { quint32 hallVersion = DJHallController::version(); quint32 gameVersion = gameItem->version(); if ( FirstVersion(hallVersion) == FirstVersion(gameVersion) && SecondVersion(hallVersion) == SecondVersion(gameVersion) ) { serverItem = static_cast(gameItem->childItem(serverId)); if ( 0 == serverItem ) { serverItem = new DJGameServerItem(serverId,gameItem,DJGameItemServerType); } serverItem->assign( existingServerItem ); m_hallController->gameTree()->setItemExpanded( gameItem, true ); //gameItem->setLoginNamePass( userName, password ); insertGame( gameItem ,serverItem ); gameItem->gameControllerCommand( GAME_COMMAND_GAME_DATA, m_buf ); } } } break; } case DJGAME_PROTOCOL_TYPE_CHAT: { djDebug()<<"***HALL***"<<"DJGAME_PROTOCOL_TYPE_CHAT"; const ChatContent *chatContent = reinterpret_cast( protocol->chBuf ); quint32 speakerId = letoh4( &chatContent->userid_speaker ); quint32 listenerId = letoh4( &chatContent->userid_listener ); quint16 gameId = makeword(chatContent->chGameClass, chatContent->chGame); djDebug()<> 16; if( m_gameItems.contains( gameId ) ) { DJGameGameItem *gameItem = m_gameItems.value( gameId ); gameItem->gameControllerCommand( GAME_COMMAND_GAME_DATA, m_buf ); } }else { if ( listenerId < MIN_USER_ID || speakerId < MIN_USER_ID ) { //some special group chat if( m_gameItems.contains( gameId ) ) { DJGameGameItem *gameItem = m_gameItems.value( gameId ); gameItem->gameControllerCommand( GAME_COMMAND_GAME_DATA, m_buf ); } }else { //user to user chat m_hallController->receiveChat( chatContent, protocol->chLanguage ); } } break; } case DJGAME_PROTOCOL_TYPE_BROADCAST: { const BroadcastHead *boardcastHead = reinterpret_cast(protocol->chBuf); quint16 gameId = makeword(boardcastHead->chGameClass, boardcastHead->chGame); if( m_gameItems.contains( gameId ) ) { DJGameGameItem *gameItem = m_gameItems.value( gameId ); gameItem->gameControllerCommand( GAME_COMMAND_GAME_DATA, m_buf ); } break; } case DJGAME_PROTOCOL_TYPE_SPEED: { djDebug()<<"***HALL***" << "DJGAME_PROTOCOL_TYPE_SPEED"; write( SpeedPackage, DJGameProtocolLength ); break; } case DJGAME_PROTOCOL_TYPE_P2P: { djDebug()<<"***HALL***" << "DJGAME_PROTOCOL_TYPE_P2P"; if ( DJGAME_PROTOCOL_P2P_SUBTYPE_AGREE == protocol->chSubType ) { djDebug() << "DJGAME_PROTOCOL_P2P_SUBTYPE_AGREE"; const DJGameP2P* p2p = reinterpret_cast(protocol->chBuf); quint32 hostId = letoh4( &p2p->host ); quint32 clientId = letoh4( &p2p->client ); djDebug() << hostId << clientId << p2p->shPort << p2p->addr_len; } break; } case DJGAME_PROTOCOL_TYPE_GETCARDS: djDebug()<<"***HALL***"<<"DJGAME_PROTOCOL_TYPE_GETCARDS"; allGamesCommand( GAME_COMMAND_GAME_DATA, m_buf ); break; default: djDebug() << "----------------------------- unknown event"; break; } //m_buf = m_buf.mid(len); m_buf.remove(0,len); } } void DJSocket::socketBytesWritten(qint64 bytes) { djDebug() << "socketBytesWritten = " << bytes; } void DJSocket::insertGame( DJGameGameItem *gameItem, DJGameServerItem* serverItem ) { djDebug() << "DJSocket::insertGame" << gameItem->id(); serverItem->setIcon(0,QIcon(hallResDir + "/image/login.png")); quint16 gameId = gameItem->id(); QString loginName = m_hallController->loginName(); djDebug() << "loginName" << loginName; DJContact* contact = m_hallController->contact( loginName ); if ( 0 == contact ) { djDebug() << "new contact" ; contact = new DJContact( m_hallController, loginName ); m_hallController->insertContact( loginName, contact ); } contact->insertGame( gameId ); gameItem->setCurServerId( serverItem->id() ); QList list; list << QVariant::fromValue(static_cast(gameItem)) << QVariant::fromValue(static_cast(this)) << QVariant::fromValue(static_cast(m_hallController)) << QVariant::fromValue(static_cast(contact)); //<< QVariant::fromValue(static_cast(m_hallController->treeContainer())) //<< QVariant::fromValue(static_cast(m_hallController->tabContainer())); DJHallInterface hallInterface( hiHallCommandProc, list ); gameItem->createGameController( hallInterface ); m_gameItems.insert( gameId, gameItem ); } void DJSocket::removeGame( quint16 gameId ) { djDebug() << "DJSocket::removeGame" << gameId << m_gameItems.size(); if ( m_gameItems.contains( gameId ) ) { djDebug() << "contains"; DJGameGameItem *gameItem = m_gameItems.take( gameId ); gameItem->setCurServerId( 0 ); for ( int i = 0; i < gameItem->childCount(); i++ ) { QTreeWidgetItem *item = (gameItem->child(i)); item->setIcon(0,QIcon()); } djDebug() << "cleanup game"; gameItem->deleteGameController(); QString loginName = m_hallController->loginName(); djDebug() << "loginName" << loginName; DJContact* contact = m_hallController->contact( loginName ); if ( contact ) { djDebug() << "contact"; contact->removeGame( gameId ); if ( contact->gameIsEmpty() ) { djDebug() << "delete contact"; m_hallController->removeContact( loginName ); delete contact; } } } if ( m_gameItems.isEmpty() ) { djDebug() << "the last game removed, close this socket"; close(); djDebug() << "socket closed"; } djDebug() << "remove end"; } bool DJSocket::containsGame( quint16 gameId ) { return m_gameItems.contains( gameId ); } void DJSocket::appendRequest( const DJClientRequest& request ) { m_requests.append( request ); } void DJSocket::removeAcl( const QList& acls ) { djDebug() << "DJSocket::removeAcl"; QList::iterator it = m_requests.begin(); while ( it != m_requests.end() ) { void* acl = (void*)(*it).aclProc(); djDebug() << "acl = " << acl; if ( acl && acls.contains( acl ) ) { djDebug() << "removed"; it = m_requests.erase(it); }else { ++it; } } } ////////////////////////////////////////////////////////////////////////////////private method void DJSocket::allGamesCommand( int gameCommand, const QVariant& parameters ) { /* QHash::const_iterator it = m_gameItems.constBegin(); while ( it != m_gameItems.constEnd() ) { DJGameGameItem* gameItem = it.value(); gameItem->gameControllerCommand( gameCommand, parameters ); ++it; } */ foreach( DJGameGameItem *gameItem, m_gameItems ) { gameItem->gameControllerCommand( gameCommand, parameters ); } } void DJSocket::aclHandler( const QByteArray& buf ) { djDebug() << "aclHandler BEGIN"; if ( m_requests.isEmpty() ) { djDebug()<<"request is empty"; return; } DJClientRequest request = m_requests.takeFirst(); request.invokeAclProc( buf ); sendBufferedRequest(); djDebug() << "aclHandler END "; } bool DJSocket::sendRequest( const DJClientRequest& request ,bool isDiscardable ) { djDebug() << "DJSocket::sendRequest"; if ( QAbstractSocket::ConnectedState != state() ) return false; DebugBuffer( request.content() ); if ( m_requests.isEmpty() ){ djDebug() << "request list is empty, just send it"; m_requests.append( request ); const QByteArray& buf = request.content(); if ( buf.size() > DJGAME_MAX_PROTOCOL_SIZE ) { djDebug()<<"too long"; write( buf, DJGAME_MAX_PROTOCOL_SIZE ); }else { write( buf ); } return true; }else { djDebug() << "request list is NOT empty"; if ( !isDiscardable ) { m_requests.append( request ); djDebug() << "buffered request"; return true; }else { djDebug() << "discard request "; return false; } } } void DJSocket::sendBufferedRequest() { djDebug() << "DJSocket::sendBufferedRequest"; if ( QAbstractSocket::ConnectedState != state() ) { djDebug()<<"socket is NOT connected"; return; } if ( m_requests.isEmpty() ) { djDebug()<<"no buffered request"; return; } const QByteArray& buf = m_requests.first().content(); DebugBuffer( buf ); if ( buf.size() > DJGAME_MAX_PROTOCOL_SIZE ) { djDebug()<<"too long"; write( buf, DJGAME_MAX_PROTOCOL_SIZE ); }else { write( buf ); } } void DJSocket::clear() { djDebug() << "------------DJSocket::clear-------------"; m_proxyCallbacks.clear(); m_ip.clear(); m_port = 0; stopProgress(); djDebug() << "receive buf count = " << m_buf.size(); DebugBuffer( m_buf ); m_buf.clear(); djDebug() << "pending requests count = "<< m_requests.count(); foreach( DJClientRequest request, m_requests ) { DebugBuffer( request.content() ); } m_requests.clear(); djDebug() << "contain gameitems count =" << m_gameItems.count(); foreach( DJGameGameItem *gameItem, m_gameItems ) { djDebug() << "game id = "<id(); removeGame( gameItem->id() ); } m_gameItems.clear(); djDebug() << "DJSocket::clear end"; } //////////////////////////////////////////////////////////////////////////////////////////////////// //proxy /* void DJSocket::getLoginNamePass( QString& userName, QString& password ) { if ( m_gameItems.size() ) { DJGameGameItem *gameItem = m_gameItems.constBegin().value(); gameItem->getLoginNamePass( userName, password ); }else { userName.clear(); password.clear(); } } */ quint32 DJSocket::ipStringToIp4( const QString& ip ) { QHostInfo info = QHostInfo::fromName(ip); quint32 ip4 = 0; if ( !info.addresses().isEmpty() ) { QHostAddress host = info.addresses().first(); ip4 = host.toIPv4Address(); } return ip4; } void DJSocket::appendProxyCallback( ProxyCallback proxyCallback ) { m_proxyCallbacks.append( proxyCallback ); } void DJSocket::connectToSocks4Proxy() { djDebug() << "connectToSocks4Proxy"; QByteArray buf( 9, 0 ); QDataStream stream( &buf, QIODevice::ReadWrite ); stream.setByteOrder( QDataStream::BigEndian ); stream << static_cast( 4 );//1 byte,version number stream << static_cast( 1 );//1 byte,command code stream << static_cast( m_port );//2 bytes,port stream << static_cast( ipStringToIp4(m_ip) );//4 bytes,ip stream << static_cast( 0 );//1 byte,end qint64 bytesWritten = 0; while ( bytesWritten < buf.size() ) { bytesWritten = write(buf); if ( -1 != bytesWritten ) { buf = buf.mid(bytesWritten); }else { //write socket error abort(); return; } } appendProxyCallback( socks4ConnectCallback ); } void DJSocket::connectToSocks5Proxy() { djDebug() << "connectToSocks5Proxy"; QByteArray buf; buf.append( 5 ); buf.append( 2 ); buf.append( static_cast( 0 ) ); buf.append( 2 ); qint64 bytesWritten = 0; while ( bytesWritten < buf.size() ) { bytesWritten = write(buf); if ( -1 != bytesWritten ) { buf = buf.mid(bytesWritten); }else { //write socket error abort(); return; } } appendProxyCallback( socks5VersionCallback ); } void DJSocket::socks5RequestAuth( QString username, QString password ) { djDebug("socks5RequestAuth"); QByteArray buf; buf.append( 1 );//version buf.append( username.toUtf8().size() );//username length buf.append( username.toUtf8() );//username string buf.append( password.toUtf8().size() );//password length buf.append( password.toUtf8() );//password string qint64 bytesWritten = 0; while ( bytesWritten < buf.size() ) { bytesWritten = write(buf); if ( -1 != bytesWritten ) { buf = buf.mid(bytesWritten); }else { //write socket error abort(); return; } } appendProxyCallback( socks5AuthCallback ); } void DJSocket::socks5RequestConnect() { djDebug("socks5RequestConnect"); QByteArray buf( 10, 0 ); QDataStream stream( &buf, QIODevice::ReadWrite ); stream.setByteOrder( QDataStream::BigEndian ); stream << static_cast( 5 );//1 byte,version number stream << static_cast( 1 );//1 byte,command code stream << static_cast( 0 );//1 byte,rsv stream << static_cast( 1 );//1 byte,atyp stream << static_cast( ipStringToIp4(m_ip) );//4 bytes,ip stream << static_cast( m_port );//2 bytes,port qint64 bytesWritten = 0; while ( bytesWritten < buf.size() ) { bytesWritten = write(buf); if ( -1 != bytesWritten ) { buf = buf.mid(bytesWritten); }else { //write socket error abort(); return; } } appendProxyCallback( socks5ConnectCallback ); } void DJSocket::connectToHttpProxy() { djDebug("connectToHttpProxy"); QByteArray buf; buf.append("CONNECT "); buf.append( m_ip ); buf.append( ":" ); buf.append( QByteArray::number(m_port) ); buf.append( " HTTP/1.1\r\nUser-Agent: BlueDJ/0.1\r\n\r\n" ); qint64 bytesWritten = 0; while ( bytesWritten < buf.size() ) { bytesWritten = write(buf); if ( -1 != bytesWritten ) { buf = buf.mid(bytesWritten); }else { //write socket error abort(); return; } } appendProxyCallback( httpConnectCallback ); } void DJSocket::timerEvent ( QTimerEvent * event ) { djDebug()<<"DJSocket::timerEvent"<