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

ChatCore.cpp

Go to the documentation of this file.
00001 //
00002 // ChatCore.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 "EDClient.h"
00025 #include "ChatSession.h"
00026 #include "ChatCore.h"
00027 #include "Buffer.h"
00028 
00029 
00030 #ifdef _DEBUG
00031 #undef THIS_FILE
00032 static char THIS_FILE[]=__FILE__;
00033 #define new DEBUG_NEW
00034 #endif
00035 
00036 CChatCore ChatCore;
00037 
00038 
00040 // CChatCore construction
00041 
00042 CChatCore::CChatCore()
00043 {
00044         m_hThread = NULL;
00045         m_bThread = FALSE;
00046 }
00047 
00048 CChatCore::~CChatCore()
00049 {
00050         Close();
00051 }
00052 
00054 // CChatCore session access
00055 
00056 POSITION CChatCore::GetIterator() const
00057 {
00058         return m_pSessions.GetHeadPosition();
00059 }
00060 
00061 CChatSession* CChatCore::GetNext(POSITION& pos) const
00062 {
00063         return (CChatSession*)m_pSessions.GetNext( pos );
00064 }
00065 
00066 int CChatCore::GetCount() const
00067 {
00068         return m_pSessions.GetCount();
00069 }
00070 
00071 BOOL CChatCore::Check(CChatSession* pSession) const
00072 {
00073         return m_pSessions.Find( pSession ) != NULL;
00074 }
00075 
00077 // CChatCore accept new connections
00078 
00079 void CChatCore::OnAccept(CConnection* pConnection, PROTOCOLID nProtocol)
00080 {
00081         CSingleLock pLock( &m_pSection );
00082         if ( ! pLock.Lock( 250 ) ) return;
00083         
00084         CChatSession* pSession = new CChatSession();
00085 
00086         pSession->m_nProtocol = nProtocol;
00087 
00088         pSession->AttachTo( pConnection );
00089 }
00090 
00091 BOOL CChatCore::OnPush(GGUID* pGUID, CConnection* pConnection)
00092 {
00093         CSingleLock pLock( &m_pSection );
00094         if ( ! pLock.Lock( 250 ) ) return FALSE;
00095         
00096         for ( POSITION pos = GetIterator() ; pos ; )
00097         {
00098                 CChatSession* pSession = GetNext( pos );
00099                 if ( pSession->OnPush( pGUID, pConnection ) ) return TRUE;
00100         }
00101         
00102         return FALSE;
00103 }
00104 
00106 // CChatCore ED2K chat handling
00107 
00108 void CChatCore::OnED2KMessage(CEDClient* pClient, CEDPacket* pPacket)
00109 {
00110         ASSERT ( pClient != NULL );
00111         // Note: Null packet is valid- in that case we have no pending message, but want to open
00112         // a chat window.
00113 
00114         CSingleLock pLock( &m_pSection );
00115         if ( ! pLock.Lock( 250 ) ) return;
00116         
00117         CChatSession* pSession = FindSession( pClient );
00118 
00119         pSession->OnED2KMessage( pPacket );
00120 }
00121 
00122 CChatSession* CChatCore::FindSession(CEDClient* pClient)
00123 {
00124         CChatSession* pSession;
00125 
00126         for ( POSITION pos = GetIterator() ; pos ; )
00127         {
00128                 pSession = GetNext( pos );
00129 
00130                 // If we already have a session
00131                 if ( ( ( ! pSession->m_bGUID ) || ( pSession->m_pGUID == pClient->m_pGUID ) ) &&
00132                          ( pSession->m_pHost.sin_addr.S_un.S_addr == pClient->m_pHost.sin_addr.S_un.S_addr ) &&
00133                          ( pSession->m_nProtocol == PROTOCOL_ED2K ) )
00134                 {
00135                         // Update details
00136                         pSession->m_bGUID               = pClient->m_bGUID;
00137                         pSession->m_pGUID               = pClient->m_pGUID;
00138                         pSession->m_pHost               = pClient->m_pHost;
00139                         pSession->m_sAddress    = pClient->m_sAddress;
00140                         pSession->m_sUserNick   = pClient->m_sNick;
00141                         pSession->m_sUserAgent  = pClient->m_sUserAgent;
00142                         pSession->m_bUnicode    = pClient->m_bEmUnicode;
00143                         pSession->m_nClientID   = pClient->m_nClientID;
00144                         pSession->m_pServer             = pClient->m_pServer;
00145 
00146                         pSession->m_bMustPush   = ( ( pClient->m_nClientID > 0 ) && ( pClient->m_nClientID < 16777216 ) );
00147 
00148                         // return existing session
00149                         return pSession;
00150                 }
00151         }
00152 
00153         // Create a new chat session
00154         pSession = new CChatSession();
00155 
00156         pSession->m_nProtocol   = PROTOCOL_ED2K;
00157         pSession->m_hSocket             = INVALID_SOCKET;                       // Should always remain invalid- has no real connection
00158         pSession->m_nState              = cssActive;
00159         pSession->m_bConnected  = TRUE;
00160         pSession->m_tConnected  = GetTickCount();
00161 
00162         // Set details
00163         pSession->m_bGUID               = pClient->m_bGUID;
00164         pSession->m_pGUID               = pClient->m_pGUID;
00165         pSession->m_pHost               = pClient->m_pHost;
00166         pSession->m_sAddress    = pClient->m_sAddress;
00167         pSession->m_sUserNick   = pClient->m_sNick;
00168         pSession->m_sUserAgent  = pClient->m_sUserAgent;
00169         pSession->m_bUnicode    = pClient->m_bEmUnicode;
00170         pSession->m_nClientID   = pClient->m_nClientID;
00171         pSession->m_pServer             = pClient->m_pServer;
00172 
00173         pSession->m_bMustPush   = ( ( pClient->m_nClientID > 0 ) && ( pClient->m_nClientID < 16777216 ) );
00174 
00175         // Make new input and output buffer objects
00176         DWORD nLimit = 0;
00177         pSession->m_pInput              = new CBuffer( &nLimit );
00178         pSession->m_pOutput             = new CBuffer( &nLimit );
00179 
00180         Add( pSession );
00181 
00182         return pSession;
00183 }
00184 
00186 // CChatCore session add and remove
00187 
00188 void CChatCore::Add(CChatSession* pSession)
00189 {
00190         CSingleLock pLock( &m_pSection, TRUE );
00191         if ( m_pSessions.Find( pSession ) == NULL ) m_pSessions.AddTail( pSession );
00192         if ( pSession->m_hSocket != INVALID_SOCKET )
00193                 WSAEventSelect( pSession->m_hSocket, m_pWakeup, FD_CONNECT|FD_READ|FD_WRITE|FD_CLOSE );
00194         StartThread();
00195 }
00196 
00197 void CChatCore::Remove(CChatSession* pSession)
00198 {
00199         CSingleLock pLock( &m_pSection, TRUE );
00200         POSITION pos = m_pSessions.Find( pSession );
00201         if ( pos != NULL ) m_pSessions.RemoveAt( pos );
00202         if ( pSession->m_hSocket != INVALID_SOCKET )
00203                 WSAEventSelect( pSession->m_hSocket, m_pWakeup, 0 );
00204 }
00205 
00206 void CChatCore::Close()
00207 {
00208         for ( POSITION pos = GetIterator() ; pos ; )
00209         {
00210                 GetNext( pos )->Close();
00211         }
00212         
00213         StopThread();
00214 }
00215 
00217 // CChatCore thread control
00218 
00219 void CChatCore::StartThread()
00220 {
00221         if ( m_hThread != NULL && m_bThread ) return;
00222         if ( GetCount() == 0 ) return;
00223         
00224         m_bThread = TRUE;
00225         CWinThread* pThread = AfxBeginThread( ThreadStart, this, THREAD_PRIORITY_NORMAL );
00226         m_hThread = pThread->m_hThread;
00227 }
00228 
00229 void CChatCore::StopThread()
00230 {
00231         if ( m_hThread == NULL ) return;
00232         
00233         m_pWakeup.SetEvent();
00234         
00235     int nAttempt = 5;
00236         for ( ; nAttempt > 0 ; nAttempt-- )
00237         {
00238                 DWORD nCode;
00239                 if ( ! GetExitCodeThread( m_hThread, &nCode ) ) break;
00240                 if ( nCode != STILL_ACTIVE ) break;
00241                 Sleep( 100 );
00242         }
00243         
00244         if ( nAttempt == 0 )
00245         {
00246                 TerminateThread( m_hThread, 0 );
00247                 theApp.Message( MSG_DEBUG, _T("WARNING: Terminating CChatCore thread.") );
00248                 Sleep( 100 );
00249         }
00250         
00251         m_hThread = NULL;
00252 }
00253 
00255 // CChatCore thread run
00256 
00257 UINT CChatCore::ThreadStart(LPVOID pParam)
00258 {
00259         CChatCore* pChatCore = (CChatCore*)pParam;
00260         pChatCore->OnRun();
00261         return 0;
00262 }
00263 
00264 void CChatCore::OnRun()
00265 {
00266         CSingleLock pLock( &m_pSection );
00267         
00268         while ( m_bThread )
00269         {
00270                 Sleep( 50 );
00271                 WaitForSingleObject( m_pWakeup, 100 );
00272                 
00273                 if ( pLock.Lock( 250 ) )
00274                 {
00275                         if ( GetCount() == 0 ) break;
00276                         
00277                         for ( POSITION pos = GetIterator() ; pos ; )
00278                         {
00279                                 GetNext( pos )->DoRun();
00280                         }
00281                         
00282                         pLock.Unlock();
00283                 }
00284         }
00285         
00286         m_bThread = FALSE;
00287 }

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