00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
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
00041
00042 CChatCore::CChatCore()
00043 {
00044 m_hThread = NULL;
00045 m_bThread = FALSE;
00046 }
00047
00048 CChatCore::~CChatCore()
00049 {
00050 Close();
00051 }
00052
00054
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
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
00107
00108 void CChatCore::OnED2KMessage(CEDClient* pClient, CEDPacket* pPacket)
00109 {
00110 ASSERT ( pClient != NULL );
00111
00112
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
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
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
00149 return pSession;
00150 }
00151 }
00152
00153
00154 pSession = new CChatSession();
00155
00156 pSession->m_nProtocol = PROTOCOL_ED2K;
00157 pSession->m_hSocket = INVALID_SOCKET;
00158 pSession->m_nState = cssActive;
00159 pSession->m_bConnected = TRUE;
00160 pSession->m_tConnected = GetTickCount();
00161
00162
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
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
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
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
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 }