1
/***************************************************************************
2
cclient.cpp - description
4
begin : Sun Sep 30 2001
5
copyright : (C) 2001-2004 by Mathias K�ster
6
email : mathen@users.berlios.de
7
***************************************************************************/
9
/***************************************************************************
11
* This program is free software; you can redistribute it and/or modify *
12
* it under the terms of the GNU General Public License as published by *
13
* the Free Software Foundation; either version 2 of the License, or *
14
* (at your option) any later version. *
16
***************************************************************************/
19
#include <sys/types.h>
25
#include <sys/socket.h>
26
#include <netinet/in.h>
34
#include <dclib/dcos.h>
35
#include <dclib/core/clist.h>
36
#include <dclib/dcobject.h>
37
#include <dclib/cquerymanager.h>
38
#include <dclib/cdownloadmanager.h>
39
#include <dclib/cconnectionmanager.h>
40
#include <dclib/cencrypt.h>
41
#include <dclib/cmessagehandler.h>
42
#include <dclib/core/cstringlist.h>
43
#include <dclib/cconfig.h>
44
#include <dclib/chubsearch.h>
57
m_bHandleUserList = TRUE;
58
m_bHandleSearch = TRUE;
59
m_bHandleMyinfo = TRUE;
60
m_bHandleForceMove = TRUE;
61
m_bHandleTransfer = TRUE;
62
m_bUpdateMyinfo = FALSE;
65
m_nNickListHandler = 0;
68
// set reconnect parameter
69
m_eReconnectState = ersNONE;
70
m_nReconnectCount = 0;
71
m_timeReconnectTimeout = 0;
72
m_timeMyinfoTimeout = 0;
77
SetCallBackFunction(0);
81
void CClient::ConnectionState( eConnectionState state )
85
CMessageConnectionState *Object = new CMessageConnectionState();
92
if ( (state == estCONNECTED) ||
93
(state == estDISCONNECTED) )
98
m_timeMyinfoTimeout = time(0);
99
m_nNickListHandler = 0;
100
m_nOpListHandler = 0;
104
m_pMessageSSL.Init();
106
// update reconnect state
107
if ( state == estCONNECTED )
109
UpdateReconnect( ersNONE );
111
if ( m_bSSLMode == TRUE )
113
if ( ChangeSocketMode(esmSSLCLIENT) == FALSE )
115
printf("change ssl mode failed\n");
121
if ( m_eReconnectState == ersFORCEMOVE )
123
UpdateReconnect( ersNONE );
127
UpdateReconnect( ersENABLED );
132
Object->m_eState = state;
133
Object->m_sMessage = GetSocketError();
135
if ( m_pCallback != 0 )
137
err = m_pCallback->notify( this, Object );
141
err = DC_CallBack( Object );
151
if ( m_bHandleMyinfo )
153
CConnectionManager::Instance()->SendMyInfoToConnectedServers();
158
void CClient::DataAvailable( const char * buffer, int len )
168
// add traffic control
169
CSocket::m_Traffic.AddTraffic(ettCONTROLRX,len);
173
s = m_sBuffer + CString().Set(buffer,len);
181
m_sBuffer = s.Mid(0,i);
182
HandleMessage( m_sBuffer );
185
if ( i == s.Length() )
191
m_sBuffer = s.Mid( i, s.Length()-i );
196
void CClient::DataTimeout()
202
void CClient::Notify()
205
if ( (m_bHandshake == FALSE) && ((time(0)-m_timeMyinfoTimeout) >= 30) )
207
if ( CConfig::Instance()->GetAwayMode() != m_MyInfo.m_eAwayMode)
209
m_MyInfo.m_eAwayMode = CConfig::Instance()->GetAwayMode();
210
m_bUpdateMyinfo = TRUE;
214
if ( (m_bHandshake == FALSE) && (m_bUpdateMyinfo == TRUE) && ((time(0)-m_timeMyinfoTimeout) >= 30) )
216
m_bUpdateMyinfo = FALSE;
217
m_timeMyinfoTimeout = time(0);
220
SendMyInfo( m_MyInfo.m_sNick, m_MyInfo.m_sComment, m_MyInfo.m_sUserSpeed, m_MyInfo.m_eAwayMode, m_MyInfo.m_sEMail, CString().setNum(m_MyInfo.m_nShared) );
223
if ( m_eReconnectState == ersENABLED )
225
if ( m_nReconnectCount >= CConfig::Instance()->GetReconnectCount() )
227
UpdateReconnect( ersNONE, 0 );
231
if ( GetConnectionState() != estNONE )
233
printf("warning, wrong reconnect state, you are connected !\n");
237
if ( m_timeReconnectTimeout == 0 )
239
m_timeReconnectTimeout = time(0);
242
if ( (time(0)-m_timeReconnectTimeout) >= CConfig::Instance()->GetReconnectTimeout() )
244
UpdateReconnect( ersNONE );
246
if ( CConfig::Instance()->GetReconnectCount() != 9999 )
258
void CClient::UpdateReconnect( eReconnectState state, int count )
260
// reconnect disabled
261
if ( CConfig::Instance()->GetReconnectCount() == 0 )
263
m_eReconnectState = ersNONE;
267
// don't change state if reconnect disables
268
if ( (m_eReconnectState == ersDISABLED) && (state != ersNONE) )
274
m_eReconnectState = state;
276
m_timeReconnectTimeout = 0;
280
m_nReconnectCount = count;
285
int CClient::HandleMessage( const CString & message )
291
CMessageHandler MessageHandler;
302
while( (type=MessageHandler.Parse(&message,pointer,Object=0)) != DC_MESSAGE_PARSE_ERROR )
311
case DC_MESSAGE_LOCK:
313
CMessageLock * msg = (CMessageLock*)Object;
315
// only handle the first lock in handshake mode
316
if ( m_bHandshake == TRUE )
318
Encrypt.Encrypt(msg->m_sData,sAnswer);
322
if ( msg->m_bExtProtocol == TRUE )
324
// quicklist ??? http://forum.dcstats.net/showthread.php?s=&threadid=802
327
SendValidateNick( m_MyInfo.m_sNick );
333
case DC_MESSAGE_LOGEDIN:
336
// if ( m_bHandleMyinfo )
337
// CConnectionManager::Instance()->SendMyInfoToConnectedServers();
342
case DC_MESSAGE_HUBNAME:
344
CMessageHubName * msg = (CMessageHubName*)Object;
346
// set the old hubname in this message
347
if ( GetHubName() != msg->m_sHubName )
348
msg->m_sOldHubName = GetHubName();
349
SetHubName(msg->m_sHubName);
354
case DC_MESSAGE_HUB_TOPIC:
356
CMessageHubTopic * msg = (CMessageHubTopic*) Object;
358
SetHubTopic(msg->m_sTopic);
363
case DC_MESSAGE_HELLO:
365
CMessageHello * msg = (CMessageHello*)Object;
367
if ( (msg->m_sNick == m_MyInfo.m_sNick) && (m_bHandshake == TRUE) )
369
SendVersion( m_sVersion );
372
if ( m_bHandleUserList == TRUE )
376
SendMyInfo( m_MyInfo.m_sNick, m_MyInfo.m_sComment, m_MyInfo.m_sUserSpeed, m_MyInfo.m_eAwayMode, m_MyInfo.m_sEMail, CString().setNum(m_MyInfo.m_nShared) );
378
m_bHandshake = FALSE;
381
if ( m_bHandleMyinfo )
382
CConnectionManager::Instance()->SendMyInfoToConnectedServers();
384
else if ( m_bHandleUserList == TRUE )
386
if ( (m_UserList.AppendUser(msg->m_sNick) == TRUE) && (!m_bHandshake) )
387
SendGetInfo(msg->m_sNick,GetNick());
389
m_pMessageSSL.JoinHub(this,msg->m_sNick);
396
case DC_MESSAGE_MYINFO:
398
CMessageMyInfo * msg = (CMessageMyInfo*)Object;
400
if( m_bHandleUserList == TRUE )
402
if ( m_UserList.UpdateUser(msg) == FALSE )
412
case DC_MESSAGE_QUIT:
414
CMessageQuit * msg = (CMessageQuit*)Object;
416
if ( m_bHandleUserList == TRUE )
418
m_UserList.RemoveUser(msg->m_sNick);
420
m_pMessageSSL.LeaveHub(this,msg->m_sNick);
427
case DC_MESSAGE_NICKLIST:
431
CMessageNickList * msg = (CMessageNickList*)Object;
433
if( m_bHandleUserList == TRUE )
435
// 0: update nicklist 1: requested nicklist
436
if ( m_nNickListHandler == 1 )
440
m_nNickListHandler = 0;
443
m_UserList.InitUserList(msg);
445
for(nick=0;(nick=msg->m_NickList.Next(nick))!=0;)
447
SendGetInfo(*nick,GetNick());
454
case DC_MESSAGE_OPLIST:
456
CMessageNickList * msg = (CMessageNickList*)Object;
458
// operators allready in the userlist
459
if( m_bHandleUserList == TRUE )
461
// init operator list
462
m_UserList.InitOperatorList(msg);
467
case DC_MESSAGE_SEARCH:
470
CMessageSearch * msg = (CMessageSearch*)Object;
472
if ( m_bHandleSearch == TRUE )
474
// check for loopback search
477
if ( msg->m_sSource == GetNick() )
484
// disable global search, compare search with own ip and port
485
if ( (msg->m_nPort == CConfig::Instance()->GetUDPListenPort()) &&
486
(msg->m_sSource == CConfig::Instance()->GetUDPHostString(FALSE)) )
492
if ( (search == TRUE) && (CQueryManager::Instance() != 0) )
494
CQueryManager::Instance()->SearchQuery( GetHubName(), GetHost(), GetNick(), msg );
501
case DC_MESSAGE_SEARCHRESULT:
503
if( m_bHandleUserList == TRUE )
505
UpdateUserSlots( (CMessageSearchResult *) Object );
508
if ( CHubSearch::Instance() )
509
if ( CHubSearch::Instance()->HandleMessage( (CMessageSearchResult *) Object ) == TRUE )
514
case DC_MESSAGE_CONNECTTOME:
516
CMessageConnectToMe * msg = (CMessageConnectToMe*) Object;
518
if ( m_bHandleTransfer == TRUE )
520
CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sHost, msg->m_nPort, GetHubName(), GetHost() );
526
case DC_MESSAGE_REVCONNECTTOME:
528
CMessageRevConnectToMe * msg = (CMessageRevConnectToMe*) Object;
530
if ( (GetMode() == ecmACTIVE) && (m_bHandleTransfer == TRUE) )
532
CString s = CConfig::Instance()->GetTCPHostString();
536
if ( CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sDstNick, "", GetHubName(), GetHost() ) == TRUE )
538
SendConnectToMe(msg->m_sDstNick,s);
546
case DC_MESSAGE_FORCEMOVE:
548
CMessageForceMove * msg = (CMessageForceMove*) Object;
550
if ( (CConfig::Instance()->GetForceMoveEnabled() == TRUE) && (m_bHandleForceMove == TRUE) )
552
SetHubName(msg->m_sHost);
554
UpdateReconnect( ersFORCEMOVE, 0 );
556
Connect(msg->m_sHost,msg->m_nPort);
562
case DC_MESSAGE_PRIVATECHAT:
564
CMessagePrivateChat * msg = (CMessagePrivateChat*) Object;
566
if ( (CConfig::Instance()->GetChatRecvOfflineMessages() == TRUE) && (m_UserList.IsUserOnline(msg->m_sSrcNick) == FALSE) )
575
m_pMessageSSL.PrivateChat(this,msg);
581
case DC_MESSAGE_CAPABILITIES:
583
m_MessageCapabilities = *((CMessageCapabilities*) Object);
595
((CDCMessage*)Object)->m_eType = type;
597
if ( m_pCallback != 0 )
599
err = m_pCallback->notify( this, Object );
603
err = DC_CallBack( Object );
617
void CClient::UpdateUserSlots( CMessageSearchResult * pSearchResult )
620
CMessageMyInfo myinfo,*mi;
622
if ( m_UserList.UpdateUserSlots(pSearchResult) == TRUE )
624
if ( m_UserList.GetUserMyInfo( pSearchResult->m_sNick, &myinfo ) == TRUE )
626
mi = new CMessageMyInfo();
629
if ( m_pCallback != 0 )
631
err = m_pCallback->notify( this, mi );
635
err = DC_CallBack( mi );
647
bool CClient::SetUserTransferInfo( CString nick, CDCMessage * msg )
651
CMessageMyInfo myinfo,*mi;
653
if ( m_UserList.SetUserTransferInfo(nick,msg) == TRUE )
655
if ( m_UserList.GetUserMyInfo( nick, &myinfo ) == TRUE )
657
mi = new CMessageMyInfo();
660
if ( m_pCallback != 0 )
662
err = m_pCallback->notify( this, mi );
666
err = DC_CallBack( mi );
681
/** send private message */
682
int CClient::SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick )
687
if ( m_UserList.IsUserOnline( sTo ) || CConfig::Instance()->GetChatSendOfflineMessages() )
690
s = m_pMessageSSL.EncryptMessage( this, sTo, sMsg );
698
i = CDCProto::SendPrivateMessage( sNick, sTo, sMsg, sFromNick );
705
int CClient::RequestNickList()
708
if (m_nNickListHandler==0) {
709
// if m_nNickListHandler == 1 we are still waiting for the nicklist, TODO handling ???
710
m_nNickListHandler = 1;
711
m_nOpListHandler = 1;
712
res = CDCProto::RequestNickList();
714
printf("Error requesting the NickList.\n");
716
printf("We are still waiting for a NickList.\n");
721
int CClient::Disconnect( bool force )
723
UpdateReconnect( ersDISABLED );
725
return CConnection::Disconnect(force);