Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

ChatWindows.cpp

Go to the documentation of this file.
00001 //
00002 // ChatWindows.cpp
00003 //
00004 // Copyright (c) Shareaza Development Team, 2002-2005.
00005 // This file is part of SHAREAZA (www.shareaza.com)
00006 //
00007 // Shareaza is free software; you can redistribute it
00008 // and/or modify it under the terms of the GNU General Public License
00009 // as published by the Free Software Foundation; either version 2 of
00010 // the License, or (at your option) any later version.
00011 //
00012 // Shareaza is distributed in the hope that it will be useful,
00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015 // GNU General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with Shareaza; if not, write to the Free Software
00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00020 //
00021 
00022 #include "StdAfx.h"
00023 #include "Shareaza.h"
00024 #include "ChatWindows.h"
00025 #include "ChatSession.h"
00026 #include "CtrlChatFrame.h"
00027 #include "CtrlPrivateChatFrame.h"
00028 #include "Buffer.h"
00029 #include "EDClient.h"
00030 #include "EDClients.h"
00031 #include "Transfers.h"
00032 #include "Neighbours.h"
00033 #include "Network.h"
00034 
00035 #ifdef _DEBUG
00036 #undef THIS_FILE
00037 static char THIS_FILE[]=__FILE__;
00038 #define new DEBUG_NEW
00039 #endif
00040 
00041 CChatWindows ChatWindows;
00042 
00043 
00045 // CChatWindows construction
00046 
00047 CChatWindows::CChatWindows()
00048 {
00049 }
00050 
00051 CChatWindows::~CChatWindows()
00052 {
00053 }
00054 
00056 // CChatWindows list access
00057 
00058 POSITION CChatWindows::GetIterator() const
00059 {
00060         return m_pList.GetHeadPosition();
00061 }
00062 
00063 CChatFrame* CChatWindows::GetNext(POSITION& pos) const
00064 {
00065         return (CChatFrame*)m_pList.GetNext( pos );
00066 }
00067 
00068 int CChatWindows::GetCount() const
00069 {
00070         return m_pList.GetCount();
00071 }
00072 
00074 // CChatWindows close all
00075 
00076 void CChatWindows::Close()
00077 {
00078         for ( POSITION pos = GetIterator() ; pos ; )
00079         {
00080                 GetNext( pos )->GetParent()->DestroyWindow();
00081         }
00082         
00083         m_pList.RemoveAll();
00084 }
00085 
00087 // CChatWindows private chat windows
00088 
00089 CPrivateChatFrame* CChatWindows::FindPrivate(GGUID* pGUID)
00090 {
00091         for ( POSITION pos = GetIterator() ; pos ; )
00092         {
00093                 CPrivateChatFrame* pFrame = reinterpret_cast<CPrivateChatFrame*>( GetNext( pos ) );
00094                 
00095                 if ( pFrame->IsKindOf( RUNTIME_CLASS(CPrivateChatFrame) ) )
00096                 {
00097                         if ( pFrame->m_pSession != NULL &&
00098                                  pFrame->m_pSession->m_bGUID &&
00099                                  pFrame->m_pSession->m_pGUID == *pGUID ) return pFrame;
00100                 }
00101         }
00102         
00103         return NULL;
00104 }
00105 
00106 CPrivateChatFrame* CChatWindows::FindPrivate(IN_ADDR* pAddress)
00107 {
00108         for ( POSITION pos = GetIterator() ; pos ; )
00109         {
00110                 CPrivateChatFrame* pFrame = reinterpret_cast<CPrivateChatFrame*>( GetNext( pos ) );
00111                 
00112                 if ( pFrame->IsKindOf( RUNTIME_CLASS(CPrivateChatFrame) ) )
00113                 {
00114                         if ( pFrame->m_pSession != NULL )
00115                         {
00116                                 if ( pFrame->m_pSession->m_pHost.sin_addr.S_un.S_addr == pAddress->S_un.S_addr )
00117                                         return pFrame;  // Regular chat window that matches
00118                                 else if ( ( pFrame->m_pSession->m_bMustPush ) &&
00119                                         ( pFrame->m_pSession->m_nProtocol == PROTOCOL_ED2K ) && 
00120                                         ( pFrame->m_pSession->m_nClientID == pAddress->S_un.S_addr ) )
00121                                         return pFrame;  // ED2K Low ID chat window that matches
00122                         }
00123                 }
00124         }
00125         
00126         return NULL;
00127 }
00128 
00129 CPrivateChatFrame* CChatWindows::FindED2KFrame(SOCKADDR_IN* pAddress)
00130 {
00131         // For High ID clients
00132         CString strHighID;
00133 
00134         strHighID.Format( _T("%s:%hu"), (LPCTSTR)CString( inet_ntoa( pAddress->sin_addr ) ), pAddress->sin_port );
00135 
00136         for ( POSITION pos = GetIterator() ; pos ; )
00137         {
00138                 CPrivateChatFrame* pFrame = reinterpret_cast<CPrivateChatFrame*>( GetNext( pos ) );
00139                 
00140                 if ( pFrame->IsKindOf( RUNTIME_CLASS(CPrivateChatFrame) ) )
00141                 {
00142                         if ( ( strHighID == pFrame->m_sNick ) && ( pFrame->m_pSession == NULL ) )
00143                         {
00144                                 return pFrame;
00145                         }
00146                 }
00147         }
00148 
00149         return NULL;
00150 }
00151 
00152 CPrivateChatFrame* CChatWindows::FindED2KFrame(DWORD nClientID, SOCKADDR_IN* pServerAddress)
00153 {
00154         // For Low ID clients
00155         
00156         if ( ( nClientID > 0 ) && ( nClientID < 16777216 ) )  // ED2K Low ID
00157         {
00158                 CString strLowID;
00159                 strLowID.Format( _T("%u@%s:%hu"),
00160                 nClientID,
00161                 (LPCTSTR)CString( inet_ntoa( pServerAddress->sin_addr ) ),
00162                 pServerAddress->sin_port );
00163 
00164                 for ( POSITION pos = GetIterator() ; pos ; )
00165                 {
00166                         CPrivateChatFrame* pFrame = reinterpret_cast<CPrivateChatFrame*>( GetNext( pos ) );
00167                         
00168                         if ( pFrame->IsKindOf( RUNTIME_CLASS(CPrivateChatFrame) ) )
00169                         {
00170                                 if ( ( strLowID == pFrame->m_sNick ) && ( pFrame->m_pSession == NULL ) )
00171                                 {
00172                                         return pFrame;
00173                                 }       
00174                         }
00175                 }
00176         }
00177 
00178         return NULL;
00179 }
00180 
00181 CPrivateChatFrame* CChatWindows::OpenPrivate(GGUID* pGUID, IN_ADDR* pAddress, WORD nPort, BOOL bMustPush, PROTOCOLID nProtocol, IN_ADDR* pServerAddress, WORD nServerPort)
00182 {
00183         SOCKADDR_IN pHost;
00184         
00185         pHost.sin_family        = PF_INET;
00186         pHost.sin_addr          = *pAddress;
00187         pHost.sin_port          = htons( nPort );
00188 
00189         if ( pServerAddress == NULL )
00190                 return OpenPrivate( pGUID, &pHost, bMustPush, nProtocol, NULL );
00191 
00192         SOCKADDR_IN pServer;
00193 
00194         pServer.sin_family      = PF_INET;
00195         pServer.sin_addr        = *pServerAddress;
00196         pServer.sin_port        = htons( nServerPort );
00197         
00198         return OpenPrivate( pGUID, &pHost, bMustPush, nProtocol, &pServer );
00199 }
00200 
00201 CPrivateChatFrame* CChatWindows::OpenPrivate(GGUID* pGUID, SOCKADDR_IN* pHost, BOOL bMustPush, PROTOCOLID nProtocol, SOCKADDR_IN* pServer)
00202 {
00203         CPrivateChatFrame* pFrame = NULL;
00204 
00205         ASSERT ( pHost != NULL );
00206 
00207         if ( ( nProtocol == PROTOCOL_BT ) || ( nProtocol == PROTOCOL_FTP ) )
00208                 return NULL;
00209 
00210         if ( ! MyProfile.IsValid() )
00211         {
00212                 CString strMessage;
00213                 LoadString( strMessage, IDS_CHAT_NEED_PROFILE );
00214                 if ( AfxMessageBox( strMessage, MB_YESNO|MB_ICONQUESTION ) == IDYES )
00215                         AfxGetMainWnd()->PostMessage( WM_COMMAND, ID_TOOLS_PROFILE );
00216                 return NULL;
00217         }
00218 
00219         if ( nProtocol == PROTOCOL_ED2K )
00220         {
00221                 CEDClient* pClient;
00222 
00223                 // First, check if it's a low ID user on another server. 
00224                 if ( bMustPush && pServer ) 
00225                 {
00226                         // It's a firewalled user (Low ID). If they are using another server, we 
00227                         // can't (shouldn't) contact them. (It places a heavy load on the ed2k servers)
00228                         CSingleLock pLock1( &Network.m_pSection );
00229                         if ( ! pLock1.Lock( 250 ) ) return NULL;
00230                         if ( Neighbours.Get( &pServer->sin_addr ) == NULL ) return NULL;
00231                         pLock1.Unlock();
00232                 }
00233 
00234                 // ED2K chat is handled by the EDClient section. (Transfers)
00235                 // We need to find (or create) an EDClient to handle this chat session, since everything 
00236                 // on ed2k shares a TCP link.
00237 
00238                 // First, lock the section to prevent a problem with other threads
00239                 CSingleLock pLock( &Transfers.m_pSection );
00240                 if ( ! pLock.Lock( 250 ) ) return NULL;
00241 
00242                 // We need to connect to them, so either find or create an EDClient
00243                 if ( pServer )
00244                         pClient = EDClients.Connect(pHost->sin_addr.S_un.S_addr, pHost->sin_port, &pServer->sin_addr, pServer->sin_port, pGUID );
00245                 else
00246                         pClient = EDClients.Connect(pHost->sin_addr.S_un.S_addr, pHost->sin_port, NULL, 0, pGUID );
00247                 // If we weren't able to create a client (Low-id and no server), then exit.
00248                 if ( ! pClient ) return NULL;
00249                 // Have it connect (if it isn't)
00250                 if ( ! pClient->m_bConnected ) pClient->Connect();
00251                 // Tell it to start a chat session as soon as it's able
00252                 pClient->OpenChat();
00253                 pLock.Unlock();
00254 
00255                 // Check for / make active any existing window
00256                 pFrame = FindPrivate( &pHost->sin_addr );
00257                 // Check for an empty frame
00258                 if ( pFrame == NULL )
00259                 {
00260                         if ( bMustPush ) pFrame = FindED2KFrame( pHost->sin_addr.S_un.S_addr, pServer );
00261                         else pFrame = FindED2KFrame( pHost );
00262                 }
00263                 if ( pFrame != NULL ) 
00264                 {
00265                         // Open window if we found one
00266                         CWnd* pParent = pFrame->GetParent();
00267                         if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
00268                         pParent->BringWindowToTop();
00269                         pParent->SetForegroundWindow();
00270                         // And exit
00271                         return pFrame;
00272                 }
00273                 // Open an empty (blank) chat frame. This is totally unnecessary- The EDClient will open 
00274                 // one as required, but it looks better to open one here.
00275                 pFrame = new CPrivateChatFrame();
00276                 // Set name (Also used to match incoming connection)
00277                 if ( bMustPush && pServer ) // Firewalled user (Low ID)
00278                 {
00279                         pFrame->m_sNick.Format( _T("%lu@%s:%hu"),
00280                         pHost->sin_addr.S_un.S_addr,
00281                         (LPCTSTR)CString( inet_ntoa( pServer->sin_addr ) ),
00282                         pServer->sin_port );
00283                 }
00284                 else    // Regular user (High ID)
00285                 {
00286                         pFrame->m_sNick.Format( _T("%s:%hu"), (LPCTSTR)CString( inet_ntoa( pHost->sin_addr ) ), pHost->sin_port );
00287                 }
00288 
00289                 // Open window
00290                 CWnd* pParent = pFrame->GetParent();
00291                 if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
00292                 pParent->BringWindowToTop();
00293                 pParent->SetForegroundWindow();
00294                 // Put a 'connecting' message in the window
00295                 CString strMessage, strConnecting;
00296                 LoadString( strConnecting, IDS_CHAT_CONNECTING_TO );
00297                 strMessage.Format( strConnecting, pFrame->m_sNick );
00298                 pFrame->OnStatusMessage( 0, strMessage );
00299 
00300                 return pFrame;
00301         }
00302 
00303         if ( pGUID != NULL ) pFrame = FindPrivate( pGUID );
00304         if ( pFrame == NULL ) pFrame = FindPrivate( &pHost->sin_addr );
00305         
00306         if ( pFrame == NULL )
00307         {
00308                 pFrame = new CPrivateChatFrame();
00309                 pFrame->Initiate( pGUID, pHost, bMustPush );    
00310         }
00311 
00312         pFrame->PostMessage( WM_COMMAND, ID_CHAT_CONNECT );
00313         
00314         CWnd* pParent = pFrame->GetParent();
00315         if ( pParent->IsIconic() ) pParent->ShowWindow( SW_SHOWNORMAL );
00316         pParent->BringWindowToTop();
00317         pParent->SetForegroundWindow();
00318 
00319         return pFrame;
00320 }
00321 
00323 // CChatWindows add and remove
00324 
00325 void CChatWindows::Add(CChatFrame* pFrame)
00326 {
00327         if ( m_pList.Find( pFrame ) == NULL ) m_pList.AddTail( pFrame );
00328 }
00329 
00330 void CChatWindows::Remove(CChatFrame* pFrame)
00331 {
00332         if ( POSITION pos = m_pList.Find( pFrame ) ) m_pList.RemoveAt( pos );
00333 }
00334 

Generated on Thu Dec 15 10:39:34 2005 for Shareaza 2.2.1.0 by  doxygen 1.4.2