// ---------------------------------------------------------------------------80 // ICQ plugin for Miranda Instant Messenger // ________________________________________ // // Copyright © 2000,2001 Richard Hughes, Roland Rabien, Tristan Van de Vreede // Copyright © 2001,2002 Jon Keating, Richard Hughes // Copyright © 2002,2003,2004 Martin Öberg, Sam Kothari, Robert Rainwater // Copyright © 2004,2005,2006 Joe Kucera // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // ----------------------------------------------------------------------------- // // File name : $Source: /cvsroot/miranda/miranda/protocols/IcqOscarJ/icq_infoupdate.c,v $ // Revision : $Revision: 2874 $ // Last change on : $Date: 2006-05-16 23:38:00 +0200 (Tue, 16 May 2006) $ // Last change by : $Author: ghazan $ // // DESCRIPTION: // // Describe me here please... // // ----------------------------------------------------------------------------- #include "icqoscar.h" #define LISTSIZE 100 static CRITICAL_SECTION listmutex; static HANDLE hQueueEvent = NULL; static HANDLE hDummyEvent = NULL; static int nUserCount = 0; static int bPendingUsers = 0; static BOOL bEnabled = TRUE; static BOOL bPaused = FALSE; static BOOL bRunning = FALSE; static DWORD tLast; static HANDLE hInfoThread = NULL; static DWORD dwUpdateThreshold; typedef struct s_userinfo { DWORD dwUin; HANDLE hContact; } userinfo; static userinfo userList[LISTSIZE]; // Retrieve users' info unsigned __stdcall icq_InfoUpdateThread(void* arg); void icq_InitInfoUpdate(void) { int i; // Create wait objects hQueueEvent = CreateEvent(NULL, FALSE, FALSE, NULL); hDummyEvent = CreateEvent(NULL, FALSE, FALSE, NULL); if (hQueueEvent && hDummyEvent) { // Init mutexes InitializeCriticalSection(&listmutex); // Init list for (i = 0; i 0) { int i, nChecked = 0; // Check if in list EnterCriticalSection(&listmutex); for (i = 0; (i dwUpdateThreshold) { // Queue user if (!icq_QueueUser(hContact)) { // The queue is full, pause queuing contacts bPendingUsers = 1; break; } } hContact = ICQFindNextContact(hContact); } icq_EnableUserLookup(bOldEnable); // wake up thread } void icq_EnableUserLookup(BOOL bEnable) { bEnabled = bEnable; if (bEnabled) bPaused = FALSE; // Notify worker thread if (bEnabled && hQueueEvent) SetEvent(hQueueEvent); } void icq_PauseUserLookup() { bPaused = TRUE; tLast = GetTickCount(); #ifdef _DEBUG NetLog_Server("Pausing Auto-info update thread..."); #endif } unsigned __stdcall icq_InfoUpdateThread(void* arg) { int i; DWORD dwWait; bRunning = TRUE; while (bRunning) { // Wait for a while ResetEvent(hQueueEvent); if (!nUserCount && bPendingUsers) // whole queue processed, check if more users needs updating icq_RescanInfoUpdate(); if ((nUserCount > 0) && bEnabled && icqOnline) dwWait = WaitForSingleObjectEx(hDummyEvent, 3000, TRUE); else { // we need to slow down the process or icq will kick us dwWait = WaitForSingleObjectEx(hDummyEvent, 1000, TRUE); while (bRunning && dwWait == WAIT_TIMEOUT) { // wait for new work or until we should end dwWait = WaitForSingleObjectEx(hQueueEvent, 10000, TRUE); } } if (!bRunning) break; switch (dwWait) { case WAIT_IO_COMPLETION: // Possible shutdown in progress break; case WAIT_OBJECT_0: case WAIT_TIMEOUT: // Time to check for new users if (!bEnabled) continue; // we can't send requests now if (bPaused) { // pause for 30sec if (GetTickCount()-tLast>30000) { bPaused = FALSE; #ifdef _DEBUG NetLog_Server("Resuming auto-info update thread..."); #endif } continue; } tLast = GetTickCount(); #ifdef _DEBUG NetLog_Server("Users %u", nUserCount); #endif if (nUserCount && icqOnline) { EnterCriticalSection(&listmutex); for (i = 0; i dwUpdateThreshold) { #ifdef _DEBUG NetLog_Server("Request info for user %u", userList[i].dwUin); #endif sendUserInfoAutoRequest(userList[i].dwUin); // Dequeue user and go back to sleep userList[i].dwUin = 0; userList[i].hContact = NULL; nUserCount--; break; } else { #ifdef _DEBUG NetLog_Server("Dequeued absolete user %u", userList[i].dwUin); #endif // Dequeue user and find another one userList[i].dwUin = 0; userList[i].hContact = NULL; nUserCount--; // continue for loop } } } LeaveCriticalSection(&listmutex); } break; default: // Something strange happened. Exit bRunning = FALSE; break; } } return 0; } // Clean up before exit void icq_InfoUpdateCleanup(void) { bRunning = FALSE; SetEvent(hDummyEvent); // break timeout SetEvent(hQueueEvent); // break queue loop if (hInfoThread) WaitForSingleObjectEx(hInfoThread, INFINITE, TRUE); // Uninit mutex DeleteCriticalSection(&listmutex); CloseHandle(hQueueEvent); CloseHandle(hDummyEvent); CloseHandle(hInfoThread); }