1 /***************************************************************************
2 cclient.cpp - description
3 -------------------
4 begin : Sun Sep 30 2001
5 copyright : (C) 2001-2004 by Mathias Küster
6 email : mathen@users.berlios.de
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
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. *
15 * *
16 ***************************************************************************/
17
18 #include "cclient.h"
19
20 #include <stdio.h>
21 #include <sys/types.h>
22
23 #ifndef WIN32
24 #include <stdlib.h>
25 #include <unistd.h>
26 #include <sys/socket.h>
27 #include <netinet/in.h>
28 #include <netdb.h>
29 #endif
30
31 #include "core/clist.h"
32 #include "dcobject.h"
33 #include "cquerymanager.h"
34 #include "cdownloadmanager.h"
35 #include "cconnectionmanager.h"
36 #include "cencrypt.h"
37 #include "cmessagehandler.h"
38 #include "cconfig.h"
39 #include "csearchmanager.h"
40 #include "clistenmanager.h"
41 #include "dclib-ssl-use.h"
42
43 // need to decompress zpipe data
44 #include "core/czlib.h"
45 #include "core/cbytearray.h"
46
47 // for DPRINTF
48 #include "dclib.h"
49
50 // IsPrivateI4() and IsValidI4()
51 #include "core/cnetaddr.h"
52
CClient(CString remoteEncoding)53 CClient::CClient( CString remoteEncoding ) : CDCProto( remoteEncoding )
54 {
55 m_pCallback = 0;
56
57 m_bHandshake = true;
58 m_bHandleUserList = true;
59 m_bHandleSearch = true;
60 m_bHandleMyinfo = true;
61 m_bHandleForceMove = true;
62 m_bHandleTransfer = true;
63 m_bUpdateMyinfo = false;
64 m_bSendMyinfo = true;
65 m_bSSLMode = false;
66 m_nNickListHandler = 0;
67 m_bUsedPassword = false;
68
69 // set reconnect parameter
70 m_eReconnectState = ersNONE;
71 m_nReconnectCount = 0;
72 m_timeReconnectTimeout = 0;
73 m_timeMyinfoTimeout = 0;
74
75 // initialise settings used since hub supports message cannot be used
76 m_bExtProtocol = false;
77 m_bGotIP = false;
78
79 // zpipe handling
80 m_pZLib = 0;
81 m_bZMode = false;
82
83 // message parser
84 m_pMessageHandler = new CMessageHandler( remoteEncoding );
85
86 #if DCLIB_HAS_SSL == 1
87 if ( CConfig::Instance() )
88 {
89 m_MyInfo.m_bTLSFlag = ( CConfig::Instance()->GetTransferCert().NotEmpty() && CConfig::Instance()->GetTransferKey().NotEmpty() );
90 }
91 #endif
92 }
93
~CClient()94 CClient::~CClient()
95 {
96 SetCallBackFunction(0);
97
98 delete m_pZLib;
99 m_pZLib = 0;
100
101 delete m_pMessageHandler;
102 m_pMessageHandler = 0;
103 }
104
105 /** */
ConnectionState(eConnectionState state)106 void CClient::ConnectionState( eConnectionState state )
107 {
108 int err = -1;
109
110 CMessageConnectionState *Object = new CMessageConnectionState();
111
112 if ( (state == estCONNECTED) ||
113 (state == estDISCONNECTED) )
114 {
115 // reset all values
116 m_sBuffer.Empty();
117 m_bHandshake = true;
118 m_timeMyinfoTimeout = time(0);
119 m_nNickListHandler = 0;
120
121 m_bExtProtocol = false;
122 m_bGotIP = false;
123
124 m_UserList.Clear();
125
126 m_bZMode = false;
127 delete m_pZLib;
128 m_pZLib = 0;
129 #if DCLIB_HAS_SSL == 1
130 m_pMessageSSL.Init();
131 #endif
132 // update reconnect state
133 if ( state == estCONNECTED )
134 {
135 UpdateReconnect( ersNONE );
136
137 if ( m_bSSLMode && CConfig::Instance() )
138 {
139 if ( ChangeSocketMode( esmSSLCLIENT, CConfig::Instance()->GetTransferCert(), CConfig::Instance()->GetTransferKey() ) == false )
140 {
141 printf("change ssl mode failed\n");
142 }
143 }
144 }
145 else
146 {
147 if ( m_eReconnectState == ersFORCEMOVE )
148 {
149 UpdateReconnect( ersNONE );
150 }
151 else
152 {
153 UpdateReconnect( ersENABLED );
154 }
155 }
156 }
157
158 Object->m_eState = state;
159 Object->m_sMessage = GetSocketError();
160
161 if ( m_pCallback != 0 )
162 {
163 err = m_pCallback->notify( this, Object );
164 }
165 else
166 {
167 err = DC_CallBack( Object );
168 }
169
170 // callback failed
171 if ( err == -1 )
172 {
173 delete Object;
174 }
175
176 // update myinfo
177 if ( m_bHandleMyinfo && CConnectionManager::Instance() )
178 {
179 CConnectionManager::Instance()->SendMyInfoToConnectedServers();
180 }
181 }
182
183 /** */
DataAvailable(const char * buffer,int len)184 void CClient::DataAvailable( const char * buffer, int len )
185 {
186 CString s;
187 int i = 0;
188
189 if ( len <= 0 )
190 {
191 return;
192 }
193
194 // add traffic control
195 CSocket::m_Traffic.AddTraffic(ettCONTROLRX,len);
196
197 if ( m_bZMode )
198 {
199 int inlen = len;
200 CString trailing;
201
202 if ( m_pZLib == 0 )
203 {
204 m_pZLib = new CZLib();
205 }
206
207 int outlen = 1024*100; // same as what CTransfer uses
208 CByteArray * out = new CByteArray(outlen);
209
210 //printf( "before inlen=%d outlen=%d ", inlen, outlen );
211 const int zlibstatus = m_pZLib->InflateZBlock( buffer, &inlen, (char*)out->Data(), &outlen );
212 //printf( "after inlen=%d outlen=%d\n", inlen, outlen );
213
214 if ( zlibstatus == -1 )
215 {
216 printf("CClient: ZPipe decompress error, returning to normal mode\n");
217 delete m_pZLib;
218 m_pZLib = 0;
219 m_bZMode = false;
220 }
221 else if ( zlibstatus == 0 )
222 {
223 //printf("ZPipe: finished decompressing data, leaving zmode\n");
224 delete m_pZLib;
225 m_pZLib = 0;
226 m_bZMode = false;
227
228 /*
229 * Check for uncompressed data after compressed data.
230 * In 0.3.19 there was usually data after the compressed data
231 * which got ignored, because it put the compressed data
232 * into m_sBuffer and did not send it to zlib until
233 * some more data was received.
234 */
235 if ( inlen < len )
236 {
237 trailing.Set( buffer+inlen, len-inlen );
238 }
239 }
240
241 if ( ((zlibstatus == 0) || (zlibstatus == 1)) && (outlen > 0) )
242 {
243 s = m_sBuffer + CString().Set((char*)out->Data(),outlen);
244 m_sBuffer.Empty();
245
246 if ( trailing.NotEmpty() )
247 {
248 s += trailing;
249 }
250
251 //printf("ZPipe result: '%s'\n",s.Data());
252 }
253
254 delete out;
255 }
256 else
257 {
258 s = m_sBuffer + CString().Set(buffer,len);
259
260 /* contents of buffer have been used, empty it to make sure it does not get used again */
261 m_sBuffer.Empty();
262 }
263
264 /* If ZPipe is enabled, we must search forwards for $ZOn|
265 * in case there is a | within the compressed data.
266 *
267 * And since hub supports negotiation is useless, we had better
268 * assume ZPipe is always enabled.
269 */
270 i = s.Find("$ZOn|");
271 if ( i >= 0 )
272 {
273 /* Handle all messages up to but not including $ZOn| */
274 HandleMessage( s.Mid(0,i) );
275
276 /* Handle $ZOn| and advance i */
277 m_bZMode = true;
278 i += 5;
279
280 if ( i < s.Length() )
281 {
282 /*
283 * Handle the compressed data.
284 */
285 DataAvailable( s.Data()+i, s.Length()-i );
286 }
287
288 return;
289 }
290
291 /* No ZPipe support or $ZOn| not found */
292 i = s.FindRev('|') + 1;
293
294 if ( i > 0 )
295 {
296 HandleMessage( s.Mid(0,i) );
297 }
298
299 if ( i < s.Length() )
300 {
301 m_sBuffer = s.Mid( i, s.Length()-i );
302 }
303 }
304
305 /** */
DataTimeout()306 void CClient::DataTimeout()
307 {
308 SendString("|");
309 }
310
311 /** */
Notify()312 void CClient::Notify()
313 {
314 if ( !CConfig::Instance() )
315 return;
316
317 // check away mode
318 if ( (m_bHandshake == false) && ((time(0)-m_timeMyinfoTimeout) >= 30) )
319 {
320 if ( CConfig::Instance()->GetAwayMode() != m_MyInfo.m_eAwayMode)
321 {
322 m_MyInfo.m_eAwayMode = CConfig::Instance()->GetAwayMode();
323 m_bUpdateMyinfo = true;
324 }
325 }
326
327 if ( (m_bHandshake == false) && m_bUpdateMyinfo && ((time(0)-m_timeMyinfoTimeout) >= 30) )
328 {
329 m_bUpdateMyinfo = false;
330 m_timeMyinfoTimeout = time(0);
331
332 if ( m_bSendMyinfo )
333 SendMyInfo( &m_MyInfo );
334 }
335
336 if ( m_eReconnectState == ersENABLED )
337 {
338 if ( m_nReconnectCount >= CConfig::Instance()->GetReconnectCount() )
339 {
340 UpdateReconnect( ersNONE, 0 );
341 }
342 else
343 {
344 if ( GetConnectionState() != estNONE )
345 {
346 printf("warning, wrong reconnect state, you are connected !\n");
347 }
348
349 // init timer
350 if ( m_timeReconnectTimeout == 0 )
351 {
352 m_timeReconnectTimeout = time(0);
353 }
354
355 if ( (time(0)-m_timeReconnectTimeout) >= CConfig::Instance()->GetReconnectTimeout() )
356 {
357 UpdateReconnect( ersNONE );
358
359 if ( CConfig::Instance()->GetReconnectCount() != 9999 )
360 {
361 m_nReconnectCount++;
362 }
363
364 Connect();
365 }
366 }
367 }
368 }
369
370 /** */
UpdateReconnect(eReconnectState state,int count)371 void CClient::UpdateReconnect( eReconnectState state, int count )
372 {
373 if ( !CConfig::Instance() )
374 return;
375
376 // reconnect disabled
377 if ( CConfig::Instance()->GetReconnectCount() == 0 )
378 {
379 m_eReconnectState = ersNONE;
380 return;
381 }
382
383 // don't change state if reconnect disables
384 if ( (m_eReconnectState == ersDISABLED) && (state != ersNONE) )
385 {
386 return;
387 }
388
389 // update state
390 m_eReconnectState = state;
391 // reset timeout
392 m_timeReconnectTimeout = 0;
393 // update counter
394 if ( count != -1 )
395 {
396 m_nReconnectCount = count;
397 }
398 }
399
400 /** */
HandleMessage(const CString & message)401 int CClient::HandleMessage( const CString & message )
402 {
403 int err;
404 int pointer;
405 eDCMessage type;
406 CDCMessage * Object = 0;
407 CString sAnswer,s;
408
409 if ( message.IsEmpty() )
410 {
411 return 0;
412 }
413
414 pointer = 0;
415
416 while( (type=m_pMessageHandler->Parse(&message,pointer,&Object)) != DC_MESSAGE_PARSE_ERROR )
417 {
418 if ( !Object )
419 {
420 continue;
421 }
422
423 switch (type)
424 {
425 case DC_MESSAGE_LOCK:
426 {
427 CMessageLock * msg = (CMessageLock*)Object;
428
429 // only handle the first lock in handshake mode
430 if ( m_bHandshake )
431 {
432 #if DCLIB_HAS_SSL == 1
433 if ( m_bSSLMode )
434 {
435 SendSSLInfo();
436 }
437 #endif
438 CEncrypt::Encrypt(msg->m_sData,sAnswer);
439
440 if ( msg->m_bExtProtocol )
441 {
442 /*
443 * Assumes NoHello NoGetINFO are supported.
444 * The hub may not inform us what is actually enabled in its supports.
445 */
446 m_bExtProtocol = true;
447
448 // HubTopic No $Hellos No $GetINFO UserCommand
449 /*
450 * UserIP2 now enabled always, if disabled we just do not use
451 * the value the hub gives us, but it gets stored in case
452 * the setting is changed without reconnecting to the hub.
453 *
454 * Similarly TTHSearch is always enabled because CConfig::Instance()->GetDisableHashList()
455 * only affects the hashing of new files. However NOTTH is added to the tag.
456 */
457 s = "HubTopic NoHello NoGetINFO TTHSearch UserCommand UserIP2 ";
458
459 if ( CConfig::Instance() != 0 )
460 {
461 if ( CConfig::Instance()->GetZPipeEnabled() )
462 {
463 // this is what DC++ 0.699 sends
464 // it may change later after testing finishes
465 s += "ZPipe0 ";
466 }
467
468 if ( CConfig::Instance()->GetCompressedTransfers() )
469 {
470 s += "GetZBlock ";
471 }
472 }
473
474 SendSupports(s);
475 // quicklist ??? http://forum.dcstats.net/showthread.php?s=&threadid=802
476 }
477
478 SendKey( sAnswer );
479
480 SendValidateNick( m_MyInfo.m_sNick );
481 }
482
483 break;
484 }
485
486 case DC_MESSAGE_LOGEDIN:
487 {
488 // update myinfo
489 // if ( m_bHandleMyinfo )
490 // CConnectionManager::Instance()->SendMyInfoToConnectedServers();
491
492 break;
493 }
494
495 case DC_MESSAGE_HUBNAME:
496 {
497 CMessageHubName * msg = (CMessageHubName*)Object;
498
499 // set the old hubname in this message
500 if ( GetHubName() != msg->m_sHubName )
501 msg->m_sOldHubName = GetHubName();
502 SetHubName(msg->m_sHubName);
503
504 break;
505 }
506
507 case DC_MESSAGE_HUB_TOPIC:
508 {
509 CMessageHubTopic * msg = (CMessageHubTopic*) Object;
510
511 SetHubTopic(msg->m_sTopic);
512
513 break;
514 }
515
516 case DC_MESSAGE_HELLO:
517 {
518 CMessageHello * msg = (CMessageHello*)Object;
519
520 if ( (msg->m_sNick == m_MyInfo.m_sNick) && m_bHandshake )
521 {
522 SendVersion();
523
524 // get nicklist
525 if ( m_bHandleUserList )
526 RequestNickList();
527
528 if ( m_bSendMyinfo )
529 SendMyInfo( &m_MyInfo );
530
531 m_bHandshake = false;
532
533 // update myinfo
534 if ( m_bHandleMyinfo && CConnectionManager::Instance() )
535 CConnectionManager::Instance()->SendMyInfoToConnectedServers();
536 }
537 else if ( m_bHandleUserList )
538 {
539 m_UserList.AppendUser(msg->m_sNick);
540 }
541
542 break;
543 }
544
545 case DC_MESSAGE_MYINFO:
546 {
547 CMessageMyInfo * msg = (CMessageMyInfo*)Object;
548
549 if ( m_bHandleUserList )
550 {
551 if ( m_UserList.UpdateUser(msg) == false )
552 {
553 delete Object;
554 Object = 0;
555 }
556 }
557
558 break;
559 }
560
561 case DC_MESSAGE_QUIT:
562 {
563 CMessageQuit * msg = (CMessageQuit*)Object;
564
565 if ( m_bHandleUserList )
566 {
567 m_UserList.RemoveUser(msg->m_sNick);
568 #if DCLIB_HAS_SSL == 1
569 m_pMessageSSL.LeaveHub(this,msg->m_sNick);
570 #endif
571 }
572
573 break;
574 }
575
576 case DC_MESSAGE_NICKLIST:
577 {
578 CMessageNickList * msg = (CMessageNickList*)Object;
579
580 if ( m_bHandleUserList )
581 {
582 // 0: update nicklist 1: requested nicklist
583 if ( m_nNickListHandler == 1 )
584 {
585 m_UserList.Clear();
586
587 m_nNickListHandler = 0;
588 }
589
590 m_UserList.InitUserList(msg);
591
592 if ( m_bExtProtocol == false )
593 {
594 for ( CString * nick = 0; (nick=msg->m_NickList.Next(nick))!=0; )
595 {
596 SendGetInfo(*nick,GetNick());
597 }
598 }
599 }
600
601 break;
602 }
603
604 case DC_MESSAGE_OPLIST:
605 {
606 CMessageOpList * msg = (CMessageOpList*)Object;
607
608 // operators allready in the userlist
609 if ( m_bHandleUserList )
610 {
611 // init operator list
612 m_UserList.InitOperatorList(msg);
613 }
614 break;
615 }
616
617 case DC_MESSAGE_SEARCH_FILE:
618 {
619 bool search = true;
620 CMessageSearchFile * msg = (CMessageSearchFile*)Object;
621
622 if ( m_bHandleSearch )
623 {
624 // check for loopback search
625 if ( msg->m_bLocal )
626 {
627 if ( msg->m_sSource == GetNick() )
628 {
629 search = false;
630 }
631 }
632 else
633 {
634 // disable global search, compare search with own ip and port
635 // also check private address space settings and IP
636 if ( CConfig::Instance() )
637 {
638 if ( (msg->m_nPort == CConfig::Instance()->GetUDPListenPort()) &&
639 (msg->m_sSource == GetExternalIP(false)) )
640 {
641 search = false;
642 }
643 else if ( ( CConfig::Instance()->GetCheckPrivateAddressSpace() &&
644 CNetAddr::IsPrivateI4(msg->m_sSource.Data()) ) ||
645 ( CConfig::Instance()->GetPrivateAddressSpaceOnly() &&
646 (CNetAddr::IsPrivateI4(msg->m_sSource.Data()) == false)) )
647 {
648 DPRINTF("Ignoring search from %s due to private address space settings\n",msg->m_sSource.Data());
649 search = false;
650 }
651 }
652 }
653
654 if ( search && (CQueryManager::Instance() != 0) )
655 {
656 CQueryManager::Instance()->SearchQuery( GetHubName(), GetResolvedIP(), GetNick(), msg );
657 }
658 }
659
660 break;
661 }
662
663 case DC_MESSAGE_SEARCHRESULT:
664 {
665 // fix hub name
666 CMessageSearchResult * msg = (CMessageSearchResult *) Object;
667 if ( msg->m_sHubName == msg->m_sHubHost )
668 {
669 msg->m_sHubName = GetHubName();
670 }
671
672 if ( CSearchManager::Instance() )
673 if ( CSearchManager::Instance()->HandleSearch( msg ) )
674 Object = 0;
675 break;
676 }
677
678 case DC_MESSAGE_CONNECTTOME:
679 {
680 CMessageConnectToMe * msg = (CMessageConnectToMe*) Object;
681
682 if ( m_bHandleTransfer )
683 {
684 if ( CDownloadManager::Instance() )
685 CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sHost, msg->m_nPort, msg->m_bCrypto, GetHubName(), GetHost() );
686 }
687
688 break;
689 }
690
691 case DC_MESSAGE_REVCONNECTTOME:
692 {
693 CMessageRevConnectToMe * msg = (CMessageRevConnectToMe*) Object;
694
695 if ( CConfig::Instance() && (GetMode() == ecmACTIVE) && m_bHandleTransfer )
696 {
697 #if DCLIB_HAS_SSL == 1
698 CMessageMyInfo usermyinfo;
699 bool crypto = ( m_MyInfo.m_bTLSFlag && m_UserList.GetUserMyInfo(msg->m_sDstNick,&usermyinfo) && usermyinfo.m_bTLSFlag );
700 #else
701 bool crypto = false;
702 #endif
703 CString s = GetExternalIP( true, crypto );
704
705 if ( s.NotEmpty() )
706 {
707 if ( CDownloadManager::Instance() &&
708 CDownloadManager::Instance()->DLM_AddTransferRequest( msg->m_sDstNick, CString(), GetHubName(), GetHost() ) )
709 {
710 SendConnectToMe(msg->m_sDstNick,s,crypto);
711 }
712 }
713 }
714
715 break;
716 }
717
718 case DC_MESSAGE_FORCEMOVE:
719 {
720 CMessageForceMove * msg = (CMessageForceMove*) Object;
721
722 if ( CConfig::Instance() &&
723 CConfig::Instance()->GetForceMoveEnabled() && m_bHandleForceMove )
724 {
725 SetHubName(msg->m_sHost);
726
727 UpdateReconnect( ersFORCEMOVE, 0 );
728
729 Connect(msg->m_sHost,msg->m_nPort);
730 }
731
732 break;
733 }
734
735 case DC_MESSAGE_PRIVATECHAT:
736 {
737 CMessagePrivateChat * msg = (CMessagePrivateChat*) Object;
738
739 /* default to receiving all messages if no CConfig */
740 if ( CConfig::Instance() &&
741 (CConfig::Instance()->GetChatRecvFromOffline() == false) &&
742 (m_UserList.IsUserOnline(msg->m_sSrcNick) == false) )
743 {
744 delete Object;
745 Object = 0;
746 msg = 0;
747 }
748 #if DCLIB_HAS_SSL == 1
749 if ( msg )
750 {
751 m_pMessageSSL.PrivateChat(this,msg);
752 }
753 #endif
754 break;
755 }
756
757 case DC_MESSAGE_SUPPORTS:
758 {
759 /*
760 * Interesting. Since hubs may not send all the strings they support
761 * it turns out there is currently nothing we can do with the supports message.
762 */
763
764 break;
765 }
766
767 case DC_MESSAGE_USERIP:
768 {
769 CMessageUserIP * msg = (CMessageUserIP*) Object;
770
771 std::list<CString>::const_iterator nick_it = msg->m_lNicks.begin();
772 std::list<CString>::const_iterator ip_it = msg->m_lIPs.begin();
773
774 while ( (nick_it != msg->m_lNicks.end()) && (ip_it != msg->m_lIPs.end()) )
775 {
776 if ( m_bHandleUserList )
777 {
778 m_UserList.SetUserIP( *nick_it, *ip_it );
779 }
780
781 if ( GetNick() == *nick_it )
782 {
783 if ( CNetAddr::IsValidI4( ip_it->Data() ) )
784 {
785 m_sExternalIP = *ip_it;
786 m_bGotIP = true;
787 }
788 }
789
790 ++nick_it;
791 ++ip_it;
792 }
793
794 break;
795 }
796
797 default:
798 {
799 break;
800 }
801 }
802
803 if (Object)
804 {
805 if ( m_pCallback != 0 )
806 {
807 err = m_pCallback->notify( this, Object );
808 }
809 else
810 {
811 err = DC_CallBack( Object );
812 }
813
814 if ( err == -1 )
815 {
816 delete Object;
817 }
818 }
819 }
820
821 return 0;
822 }
823
824 /** */
SetUserTransferInfo(CString nick,CDCMessage * msg)825 bool CClient::SetUserTransferInfo( CString nick, CDCMessage * msg )
826 {
827 int err;
828 bool res = false;
829 CMessageMyInfo myinfo,*mi;
830
831 if ( m_UserList.SetUserTransferInfo(nick,msg) )
832 {
833 if ( m_UserList.GetUserMyInfo( nick, &myinfo ) )
834 {
835 mi = new CMessageMyInfo();
836 *mi = myinfo;
837
838 if ( m_pCallback != 0 )
839 {
840 err = m_pCallback->notify( this, mi );
841 }
842 else
843 {
844 err = DC_CallBack( mi );
845 }
846
847 if ( err == -1 )
848 {
849 delete mi;
850 }
851
852 res = true;
853 }
854 }
855
856 return res;
857 }
858
859 /** send private message */
SendPrivateMessage(CString sNick,CString sTo,CString sMsg,CString sFromNick)860 int CClient::SendPrivateMessage( CString sNick, CString sTo, CString sMsg, CString sFromNick )
861 {
862 int i=-1;
863 CString s;
864
865 if ( (CConfig::Instance() && CConfig::Instance()->GetChatSendToOffline()) ||
866 m_UserList.IsUserOnline( sTo ) )
867 {
868 #if DCLIB_HAS_SSL == 1
869 s = m_pMessageSSL.EncryptMessage( this, sTo, sMsg );
870
871 if ( s.NotEmpty() )
872 {
873 sMsg = s;
874 }
875 #endif
876
877 i = CDCProto::SendPrivateMessage( sNick, sTo, sMsg, sFromNick );
878 }
879
880 return i;
881 }
882
883 /** */
RequestNickList()884 int CClient::RequestNickList()
885 {
886 int res = 0;
887
888 if ( m_nNickListHandler == 0 )
889 {
890 res = CDCProto::RequestNickList();
891
892 // if set, we will never recv a nicklist
893 // hubs may not put NoGetINFO into their supports even if it is enabled
894 if ( m_bExtProtocol == false )
895 {
896 m_nNickListHandler = 1;
897 }
898 }
899 else
900 {
901 printf("We are still waiting for a NickList.\n");
902 }
903
904 return res;
905 }
906
907 /** */
Disconnect(bool force)908 int CClient::Disconnect( bool force )
909 {
910 UpdateReconnect( ersDISABLED );
911
912 SetUsedPassword(false);
913
914 return CConnection::Disconnect(force);
915 }
916
917 /** */
GetExternalIP(bool addport,bool crypto) const918 CString CClient::GetExternalIP( bool addport, bool crypto ) const
919 {
920 /*
921 * If the hub does not support UserIP2 then the value we got from CConfig
922 * will be used.
923 */
924 if ( CConfig::Instance() && (CConfig::Instance()->GetUserIP2Enabled() == false) )
925 {
926 return CConfig::Instance()->GetTCPHostString( addport, crypto );
927 }
928 else if ( m_bGotIP )
929 {
930 if ( addport )
931 {
932 unsigned int port = 0;
933
934 if ( crypto )
935 {
936 if ( CCryptoListenManager::Instance() )
937 {
938 port = CCryptoListenManager::Instance()->GetListenPort();
939 }
940 }
941 else
942 {
943 if ( CListenManager::Instance() )
944 {
945 port = CListenManager::Instance()->GetListenPort();
946 }
947 }
948
949 if ( port != 0 )
950 {
951 return m_sExternalIP + ":" + CString::number(port);
952 }
953 else
954 {
955 return m_sExternalIP;
956 }
957 }
958 else
959 {
960 return m_sExternalIP;
961 }
962 }
963 else if ( CConfig::Instance() )
964 {
965 return CConfig::Instance()->GetTCPHostString( addport, crypto );
966 }
967 else
968 {
969 /* no IP from hub and no CConfig to get one from! */
970 return "127.0.0.1";
971 }
972 }
973
974 /** */
SendSearch(CMessageSearchFile * msg)975 int CClient::SendSearch( CMessageSearchFile * msg )
976 {
977
978 if ( msg->m_bLocal )
979 {
980 /* fix nick for passive search */
981 msg->m_sSource = GetNick();
982 }
983 else
984 {
985 /*
986 * GetExternalIP() handles if we have an IP from the hub and if we are supposed to use it or not
987 * it uses GetTCPHostString() but without adding the port this is the same as GetUDPHostString()
988 */
989 msg->m_sSource = GetExternalIP(false,false) + ":" + CString::number(CConfig::Instance()->GetUDPListenPort());
990 }
991
992 return CDCProto::SendSearch( msg );
993 }
994
995 /** */
SendSSLInfo()996 void CClient::SendSSLInfo()
997 {
998 CMessageLog * log1 = new CMessageLog();
999
1000 log1->sMessage = GetSSLVersion();
1001 log1->sMessage += " connection using ";
1002 log1->sMessage += GetSSLCipher();
1003
1004 int err;
1005 if ( m_pCallback )
1006 {
1007 err = m_pCallback->notify( this, log1 );
1008 }
1009 else
1010 {
1011 err = DC_CallBack( log1 );
1012 }
1013
1014 if ( err == -1 )
1015 {
1016 delete log1;
1017 }
1018
1019 CMessageLog * log2 = new CMessageLog();
1020 log2->sMessage = VerifyPeerCertificate();
1021
1022 if ( m_pCallback )
1023 {
1024 err = m_pCallback->notify( this, log2 );
1025 }
1026 else
1027 {
1028 err = DC_CallBack( log2 );
1029 }
1030
1031 if ( err == -1 )
1032 {
1033 delete log2;
1034 }
1035 }
1036