/* * xfirelib - C++ Library for the xfire protocol. * Copyright (C) 2006 by * Beat Wolf / http://gfire.sf.net * Herbert Poul / http://goim.us * http://xfirelib.sphene.net * * 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; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "stdafx.h" #include "xdebug.h" #include "client.h" #include "clientinformationpacket.h" #include "clientversionpacket.h" #include "xfirepacket.h" #include "authpacket.h" #include "clientloginpacket.h" #include "buddylistnamespacket.h" #include "messagepacket.h" #include "sendmessagepacket.h" #include "messageackpacket.h" #include "recvoldversionpacket.h" #include "sendkeepalivepacket.h" #include "baseProtocol.h" #include //#define XFIRE_HOST "cs.xfire.com" #define XFIRE_HOST "206.220.42.147" #define XFIRE_PORT 25999 extern BOOL mySleep(int ms,HANDLE evt); extern HANDLE hConnectionClose; extern WINBASEAPI BOOL WINAPI ResetEvent( __in HANDLE hEvent ); //#define UINT_8 unsigned char //#define UINT_32 unsigned long namespace xfirelib { using namespace std; Client::Client() { XDEBUG(("Client constructor...\n")); gameResolver = NULL; packetReader = new PacketReader(NULL); packetReader->addPacketListener( this ); buddyList = new BuddyList( this ); socket=NULL; #ifndef NO_PTHREAD sendpingthread.p=NULL; readthread.p=NULL; #endif } Client::~Client(){ XDEBUG(("Client destructor...\n")); delete username; delete password; delete buddyList; delete packetReader; delete socket; } void Client::connect( string username, string password, int useproxy, string proxyip, int proxyport) { try { this->gotBudduyList=FALSE; this->username = new string(username); this->password = new string(password); socket = new Socket( XFIRE_HOST, XFIRE_PORT,useproxy,proxyip,proxyport ); //bevors losgeht, erstmal die localaddr sichern struct sockaddr_in sa; int iLen = sizeof(sa); getsockname(socket->m_sock, (SOCKADDR*)&sa, &iLen); strcpy(this->localaddr,inet_ntoa(sa.sin_addr)); this->llocaladdr=inet_addr(this->localaddr); packetReader->setSocket(socket); ResetEvent(hConnectionClose); startThreads(); //packetReader->startListening(); socket->send("UA01"); XDEBUG(("Sent UA01\n")); ClientInformationPacket *infoPacket = new ClientInformationPacket(); this->send( infoPacket ); delete infoPacket; XINFO(("sent ClientInformationPacket\n")); ClientVersionPacket *versionPacket = new ClientVersionPacket(); versionPacket->setProtocolVersion( protocolVersion); this->send( versionPacket ); delete versionPacket; XINFO(("sent ClientVersionPacket\n")); this->connected=TRUE; } catch( SocketException ex ) { XERROR(("Socket Exception ?! %s \n",ex.description().c_str() )); this->connected=FALSE; } } XFireGameResolver *Client::getGameResolver() { return gameResolver; } void Client::startThreads() { XINFO(("About to start thread\n")); #ifndef NO_PTHREAD void* (*func)(void*) = &xfirelib::Client::startReadThread; pthread_create( &readthread, NULL, func, (void*)this ); void* (*func2)(void*) = &xfirelib::Client::startSendPingThread; pthread_create( &sendpingthread, NULL, func2, (void*)this ); #else //mir_create!!!! mir_forkthread(xfirelib::Client::startReadThread,(LPVOID)this); mir_forkthread(xfirelib::Client::startSendPingThread,(LPVOID)this); #endif } #ifndef NO_PTHREAD void *Client::startReadThread(void *ptr) { #else void Client::startReadThread(LPVOID lParam) { void* ptr=(void*)lParam; #endif if(ptr==NULL||((Client*)ptr)->packetReader==NULL) #ifndef NO_PTHREAD return NULL; #else return; #endif try { ((Client*)ptr)->packetReader->run(); } catch (SocketException ex) { XERROR(("Socket Exception ?! %s \n",ex.description().c_str() )); //miranda bescheid geben, wir haben verbindung verloren if(ptr==NULL||((Client*)ptr)->connected) SetStatus(ID_STATUS_OFFLINE,NULL); //((Client*)ptr)->disconnect(); } #ifndef NO_PTHREAD return NULL; #else return; #endif } #ifndef NO_PTHREAD void *Client::startSendPingThread(void *ptr) { Client *me = (Client*)ptr; #else void Client::startSendPingThread(LPVOID lParam) { Client *me = (Client*)lParam; #endif SendKeepAlivePacket packet; while(1) { #ifndef NO_PTHREAD pthread_testcancel(); #endif //Sleep(60000); // Sleep for 40 sek if(mySleep(60000,hConnectionClose)) { #ifndef NO_PTHREAD return NULL; #else return; #endif } #ifndef NO_PTHREAD pthread_testcancel(); #endif XDEBUG(( "Sending KeepAlivePacket\n" )); if(!me->send( &packet )) { XINFO(( "Could not send KeepAlivePacket... exiting thread.\n" )); break; } } #ifndef NO_PTHREAD return NULL; #else return; #endif } void Client::disconnect() { this->connected=FALSE; //socket vom packetreader auf NULL, damit die readschleife geschlossen wird if(this->packetReader!=NULL) this->packetReader->setSocket(NULL); XDEBUG( "cancelling readthread... \n"); #ifndef NO_PTHREAD if(readthread.p!=NULL) pthread_cancel (readthread); readthread.p=NULL; XDEBUG( "cancelling sendpingthread... \n"); if(sendpingthread.p!=NULL) pthread_cancel (sendpingthread); sendpingthread.p=NULL; #endif XDEBUG( "deleting socket...\n" ); if(socket){ delete socket; socket = NULL; } XDEBUG(( "done\n" )); } bool Client::send( XFirePacketContent *content ) { if(!socket) { XERROR(( "Trying to send content packet altough socket is NULL ! (ignored)\n" )); return false; } XFirePacket *packet = new XFirePacket(content); packet->sendPacket( socket ); delete packet; return true; } void Client::addPacketListener( PacketListener *listener ) { packetReader->addPacketListener( listener ); } void Client::receivedPacket( XFirePacket *packet ) { XDEBUG(("Client::receivedPacket\n")); if( packet == NULL ) { XERROR(("packet is NULL !!!\n")); return; } if( packet->getContent() == NULL ) { XERROR(("ERRRR getContent() returns null ?!\n")); return; } XFirePacketContent *content = packet->getContent(); switch( content->getPacketId() ) { case XFIRE_PACKET_AUTH_ID: { XINFO(("Got Auth Packet .. Sending Login\n")); AuthPacket *authPacket = (AuthPacket*)packet->getContent(); ClientLoginPacket *login = new ClientLoginPacket(); login->setSalt( authPacket->getSalt() ); login->setUsername( *username ); login->setPassword( *password ); send( login ); delete login; break; } case XFIRE_MESSAGE_ID: { XDEBUG(( "Got Message, sending ACK\n" )); MessagePacket *message = (MessagePacket*)packet->getContent(); if(message->getMessageType() == 0){ MessageACKPacket *ack = new MessageACKPacket(); memcpy(ack->sid,message->getSid(),16); ack->imindex = message->getImIndex(); send( ack ); delete ack; }else if(message->getMessageType() == 2){ send(message); } break; } default: //cout << "Nothing here... " << endl; break; } } };