|
Mixe for Privacy and Anonymity in the Internet
|
00001 /* 00002 Copyright (c) 2000, The JAP-Team 00003 All rights reserved. 00004 Redistribution and use in source and binary forms, with or without modification, 00005 are permitted provided that the following conditions are met: 00006 00007 - Redistributions of source code must retain the above copyright notice, 00008 this list of conditions and the following disclaimer. 00009 00010 - Redistributions in binary form must reproduce the above copyright notice, 00011 this list of conditions and the following disclaimer in the documentation and/or 00012 other materials provided with the distribution. 00013 00014 - Neither the name of the University of Technology Dresden, Germany nor the names of its contributors 00015 may be used to endorse or promote products derived from this software without specific 00016 prior written permission. 00017 00018 00019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS 00020 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 00021 AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS 00022 BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 00023 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 00024 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 00025 IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE 00027 */ 00028 #include "StdAfx.h" 00029 #ifndef ONLY_LOCAL_PROXY 00030 #include "CAFirstMixChannelList.hpp" 00031 #include "CAUtil.hpp" 00032 #include "CAMsg.hpp" 00033 #include "CAThread.hpp" 00034 #define MAX_HASH_KEY 8200 //8113 00035 00036 #ifdef PAYMENT 00037 #include "CAAccountingInstance.hpp" 00038 #endif 00039 00040 const SINT32 CAFirstMixChannelList::EXPIRATION_TIME_SECS = 300; // 5 minutes 00041 00042 00043 CAFirstMixChannelList::CAFirstMixChannelList() 00044 { 00045 m_HashTable=new LP_fmHashTableEntry[MAX_HASH_KEY]; 00046 memset(m_HashTable,0,sizeof(LP_fmHashTableEntry)*MAX_HASH_KEY); 00047 for(int i=0;i<MAX_HASH_KEY;i++) 00048 { 00049 m_HashTable[i]=new fmHashTableEntry; 00050 memset(m_HashTable[i],0,sizeof(fmHashTableEntry)); 00051 #ifdef PAYMENT 00052 m_HashTable[i]->cleanupNotifier = new CAConditionVariable(); 00053 #endif 00054 } 00055 m_listHashTableHead=NULL; 00056 m_listHashTableNext=NULL; 00057 #ifdef PAYMENT 00058 m_listTimoutHead = NULL; 00059 m_listTimoutFoot = NULL; 00060 #endif 00061 m_HashTableOutChannels=new LP_fmChannelListEntry[0x10000]; 00062 memset(m_HashTableOutChannels,0,sizeof(LP_fmChannelListEntry)*0x10000); 00063 #ifdef DO_TRACE 00064 m_aktAlloc=m_maxAlloc=0; 00065 #endif 00066 #ifdef DELAY_USERS 00067 m_u32DelayChannelUnlimitTraffic=DELAY_USERS_TRAFFIC; 00068 m_u32DelayChannelBucketGrow=DELAY_USERS_BUCKET_GROW; 00069 m_u32DelayChannelBucketGrowIntervall=DELAY_USERS_BUCKET_GROW_INTERVALL; 00070 m_pDelayBuckets=new volatile UINT32*[MAX_POLLFD]; 00071 memset(m_pDelayBuckets,0,sizeof(UINT32*)*MAX_POLLFD); 00072 m_pMutexDelayChannel=new CAMutex(); 00073 m_pThreadDelayBucketsLoop=new CAThread((UINT8*)"Delay Channel Thread"); 00074 m_bDelayBucketsLoopRun=true; 00075 m_pThreadDelayBucketsLoop->setMainLoop(fml_loopDelayBuckets); 00076 m_pThreadDelayBucketsLoop->start(this); 00077 #endif 00078 } 00079 00080 CAFirstMixChannelList::~CAFirstMixChannelList() 00081 { 00082 #ifdef DELAY_USERS 00083 m_bDelayBucketsLoopRun=false; 00084 m_pThreadDelayBucketsLoop->join(); 00085 delete m_pThreadDelayBucketsLoop; 00086 m_pThreadDelayBucketsLoop = NULL; 00087 delete m_pMutexDelayChannel; 00088 m_pMutexDelayChannel = NULL; 00089 delete []m_pDelayBuckets; 00090 m_pDelayBuckets = NULL; 00091 #endif 00092 for(int i=0;i<MAX_HASH_KEY;i++) 00093 { 00094 00095 #ifdef PAYMENT 00096 delete m_HashTable[i]->cleanupNotifier; 00097 m_HashTable[i]->cleanupNotifier = NULL; 00098 #endif 00099 delete m_HashTable[i]; 00100 m_HashTable[i] = NULL; 00101 } 00102 delete []m_HashTable; 00103 m_HashTable = NULL; 00104 delete []m_HashTableOutChannels; 00105 m_HashTableOutChannels = NULL; 00106 } 00107 00115 #ifndef LOG_DIALOG 00116 fmHashTableEntry* CAFirstMixChannelList::add(CAMuxSocket* pMuxSocket,const UINT8 peerIP[4],CAQueue* pQueueSend,UINT8* controlChannelKeySent,UINT8* controlChannelKeyRecv) 00117 #else 00118 fmHashTableEntry* CAFirstMixChannelList::add(CAMuxSocket* pMuxSocket,const UINT8 peerIP[4],CAQueue* pQueueSend,UINT8* strDialog) 00119 #endif 00120 { 00121 INIT_STACK; 00122 BEGIN_STACK("CAFirstMixChannelList::add"); 00123 00124 if(pMuxSocket==NULL) 00125 { 00126 FINISH_STACK("CAFirstMixChannelList::add (null socket)"); 00127 return NULL; 00128 } 00129 SINT32 hashkey=pMuxSocket->getHashKey(); 00130 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00131 { 00132 FINISH_STACK("CAFirstMixChannelList::add (invalid hash key)"); 00133 return NULL; 00134 } 00135 m_Mutex.lock(); 00136 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00137 if(pHashTableEntry->pMuxSocket!=NULL) //the entry in the hashtable for this socket (hashkey) must be empty 00138 { 00139 FINISH_STACK("CAFirstMixChannelList::add (socket exists)"); 00140 m_Mutex.unlock(); 00141 return NULL; 00142 } 00143 00144 //SAVE_STACK("CAFirstMixChannelList::add", "initialising table entry"); 00145 #ifdef CH_LOG_STUDY 00146 pHashTableEntry->channelOpenedLastIntervalTS = 0; 00147 #endif 00148 pHashTableEntry->pMuxSocket=pMuxSocket; 00149 pHashTableEntry->pQueueSend=pQueueSend; 00150 pHashTableEntry->pControlMessageQueue = new CAQueue(); 00151 pHashTableEntry->pControlChannelDispatcher = new CAControlChannelDispatcher(pHashTableEntry->pControlMessageQueue,controlChannelKeyRecv,controlChannelKeySent); 00152 pHashTableEntry->uAlreadySendPacketSize=-1; 00153 pHashTableEntry->cNumberOfChannels=0; 00154 #ifdef LOG_TRAFFIC_PER_USER 00155 pHashTableEntry->trafficIn=0; 00156 pHashTableEntry->trafficOut=0; 00157 getcurrentTimeMillis(pHashTableEntry->timeCreated); 00158 #endif 00159 #ifdef LOG_DIALOG 00160 pHashTableEntry->strDialog=new UINT8[strlen((char*)strDialog)+1]; 00161 strcpy((char*)pHashTableEntry->strDialog,(char*)strDialog); 00162 #endif 00163 // TODO Collisions? Is the id still used somewhere? 00164 //Yes it is --> for logging to match login /logout 00165 //collisions in a hard seens are an issue, but are very unlikely; and because it is only for logging it does not really matter... 00166 getRandom(&(pHashTableEntry->id)); 00167 00168 #ifdef PAYMENT 00169 pHashTableEntry->pAccountingInfo=NULL; 00170 #endif 00171 00172 SAVE_STACK("CAFirstMixChannelList::add", "copying peer IP"); 00173 memcpy(pHashTableEntry->peerIP,peerIP,4); 00174 #ifdef DATA_RETENTION_LOG 00175 pHashTableEntry->peerPort=pMuxSocket->getCASocket()->getPeerPort(); 00176 #endif 00177 #ifdef DELAY_USERS 00178 m_pMutexDelayChannel->lock(); 00179 pHashTableEntry->delayBucket=m_u32DelayChannelUnlimitTraffic; //can always send some first packets 00180 for(UINT32 i=0;i<MAX_POLLFD;i++) 00181 { 00182 if(m_pDelayBuckets[i]==NULL) 00183 { 00184 pHashTableEntry->delayBucketID=i; 00185 break; 00186 } 00187 } 00188 m_pDelayBuckets[pHashTableEntry->delayBucketID]=&pHashTableEntry->delayBucket; 00189 m_pMutexDelayChannel->unlock(); 00190 #endif 00191 00192 SAVE_STACK("CAFirstMixChannelList::add", "inserting in connection list"); 00193 //now insert the new connection in the list of all open connections 00194 if(m_listHashTableHead==NULL) //if first one 00195 { 00196 pHashTableEntry->list_HashEntries.next=NULL; 00197 } 00198 else 00199 {//add to the head of the double linked list 00200 pHashTableEntry->list_HashEntries.next=m_listHashTableHead; 00201 m_listHashTableHead->list_HashEntries.prev=pHashTableEntry; 00202 } 00203 pHashTableEntry->list_HashEntries.prev=NULL; 00204 m_listHashTableHead=pHashTableEntry; 00205 00206 SAVE_STACK("CAFirstMixChannelList::add", "inserting in timout list"); 00207 // insert in timeout list; entries are added to the foot of the list 00208 #ifdef PAYMENT 00209 pHashTableEntry->bRecoverTimeout = true; 00210 pHashTableEntry->kickoutSendRetries = MAX_KICKOUT_RETRIES; 00211 /* Hot fix: push timeout entry explicitly to avoid 00212 * confusion, when timeout occurs during AI login 00213 */ 00214 //pushTimeoutEntry_internal(pHashTableEntry); 00215 #endif 00216 m_Mutex.unlock(); 00217 00218 FINISH_STACK("CAFirstMixChannelList::add"); 00219 00220 return pHashTableEntry; 00221 } 00222 00224 #define MAX_NUMBER_OF_CHANNELS CHANNELS_PER_CLIENT 00225 00235 SINT32 CAFirstMixChannelList::addChannel(CAMuxSocket* pMuxSocket,HCHANNEL channelIn, 00236 CASymCipher* pCipher,HCHANNEL* channelOut) 00237 { 00238 if(pMuxSocket==NULL||channelOut==NULL) 00239 return E_UNKNOWN; 00240 SINT32 hashkey=pMuxSocket->getHashKey(); 00241 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00242 return E_UNKNOWN; 00243 m_Mutex.lock(); 00244 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00245 if(pHashTableEntry->pMuxSocket==NULL||pHashTableEntry->cNumberOfChannels>=MAX_NUMBER_OF_CHANNELS) 00246 { 00247 CAMsg::printMsg(LOG_DEBUG,"More than 50 channels!\n"); 00248 m_Mutex.unlock(); 00249 return E_UNKNOWN; 00250 } 00251 fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; 00252 #ifndef DO_TRACE 00253 fmChannelListEntry* pNewEntry=new fmChannelListEntry; 00254 #else 00255 fmChannelListEntry* pNewEntry=newChannelListEntry(); 00256 #endif 00257 memset(pNewEntry,0,sizeof(fmChannelListEntry)); 00258 pNewEntry->pCipher=pCipher; 00259 pNewEntry->channelIn=channelIn; 00260 00261 do 00262 { 00263 getRandom(channelOut); //get new Random OUT-CHANNEL-ID 00264 } while(*channelOut<256||get_intern_without_lock(*channelOut)!=NULL); //until it is unused... 00265 pNewEntry->channelOut=*channelOut; 00266 pNewEntry->bIsSuspended=false; 00267 pNewEntry->pHead=pHashTableEntry; 00268 00269 #ifdef LOG_CHANNEL 00270 pNewEntry->packetsInFromUser=0; 00271 pNewEntry->packetsOutToUser=0; 00272 #endif 00273 #ifdef SSL_HACK 00274 pNewEntry->downStreamBytes = 0; 00275 #endif 00276 00277 00278 00279 //add to the channel list for the given connection 00280 if(pEntry==NULL) //First Entry to the channel list 00281 { 00282 pNewEntry->list_InChannelPerSocket.next=NULL; 00283 pNewEntry->list_InChannelPerSocket.prev=NULL; 00284 } 00285 else 00286 { 00287 pNewEntry->list_InChannelPerSocket.next=pEntry; 00288 pNewEntry->list_InChannelPerSocket.prev=NULL; 00289 pEntry->list_InChannelPerSocket.prev=pNewEntry; 00290 } 00291 pHashTableEntry->pChannelList=pNewEntry; 00292 00293 //add to the out-channel list 00294 hashkey=(*channelOut)&0x0000FFFF; 00295 pEntry=m_HashTableOutChannels[hashkey]; 00296 if(pEntry!=NULL) //Hash Table Bucket Over run.... 00297 { 00298 pNewEntry->list_OutChannelHashTable.prev=NULL; 00299 pNewEntry->list_OutChannelHashTable.next=pEntry; 00300 pEntry->list_OutChannelHashTable.prev=pNewEntry; 00301 } 00302 m_HashTableOutChannels[hashkey]=pNewEntry; 00303 pHashTableEntry->cNumberOfChannels++; 00304 m_Mutex.unlock(); 00305 return E_SUCCESS; 00306 } 00307 00308 00314 fmHashTableEntry* CAFirstMixChannelList::get(CAMuxSocket* pMuxSocket) 00315 { 00316 if(pMuxSocket==NULL) 00317 return NULL; 00318 SINT32 hashkey=pMuxSocket->getHashKey(); 00319 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00320 return NULL; 00321 m_Mutex.lock(); 00322 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00323 m_Mutex.unlock(); 00324 return pHashTableEntry; 00325 } 00326 00333 fmChannelListEntry* CAFirstMixChannelList::get(CAMuxSocket* pMuxSocket,HCHANNEL channelIn) 00334 { 00335 if(pMuxSocket==NULL) 00336 return NULL; 00337 SINT32 hashkey=pMuxSocket->getHashKey(); 00338 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00339 return NULL; 00340 m_Mutex.lock(); 00341 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00342 fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; 00343 while(pEntry!=NULL) 00344 { 00345 if(pEntry->channelIn==channelIn) 00346 { 00347 m_Mutex.unlock(); 00348 return pEntry; 00349 } 00350 pEntry=pEntry->list_InChannelPerSocket.next; 00351 } 00352 m_Mutex.unlock(); 00353 return NULL; 00354 } 00355 #ifdef PAYMENT 00356 00357 inline fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry() 00358 { 00359 return popTimeoutEntry(false); 00360 } 00361 00362 fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry(bool a_bForce) 00363 { 00364 fmHashTableEntry* ret; 00365 00366 m_Mutex.lock(); 00367 ret = popTimeoutEntry_internal(a_bForce); 00368 m_Mutex.unlock(); 00369 00370 return ret; 00371 } 00372 00373 bool CAFirstMixChannelList::isTimedOut(fmHashTableEntry* pHashTableEntry) 00374 { 00375 bool ret = false; 00376 00377 m_Mutex.lock(); 00378 ret = isTimedOut_internal(pHashTableEntry); 00379 m_Mutex.unlock(); 00380 00381 return ret; 00382 } 00383 00384 bool CAFirstMixChannelList::isKickoutForced(fmHashTableEntry* pHashTableEntry) 00385 { 00386 bool ret = false; 00387 m_Mutex.lock(); 00388 ret = isKickoutForced_internal(pHashTableEntry); 00389 m_Mutex.unlock(); 00390 return ret; 00391 } 00392 void CAFirstMixChannelList::setKickoutForced(fmHashTableEntry* pHashTableEntry, bool kickoutForced) 00393 { 00394 m_Mutex.lock(); 00395 setKickoutForced_internal(pHashTableEntry, kickoutForced); 00396 m_Mutex.unlock(); 00397 } 00398 00399 #ifdef PAYMENT 00400 00405 bool CAFirstMixChannelList::forceKickout(fmHashTableEntry* pHashTableEntry, const XERCES_CPP_NAMESPACE::DOMDocument *pErrDoc) 00406 { 00407 bool ret = false; 00408 m_Mutex.lock(); 00409 ret = (pHashTableEntry->pMuxSocket != NULL); 00410 if(ret) 00411 { 00412 if(pErrDoc != NULL) 00413 { 00414 //NOTE: accessing the control channel in this case works without further locking, 00415 //because the control channel is only deleted when the Dispatcher deletes all channels. 00416 //This happens when the table entry is removed by CAFirstMixChannelList::remove 00417 //which locks over m_Mutex. 00418 pHashTableEntry->pAccountingInfo->pControlChannel->sendXMLMessage(pErrDoc); 00419 } 00420 setKickoutForced_internal(pHashTableEntry, KICKOUT_FORCED); 00421 } 00422 m_Mutex.unlock(); 00423 return ret; 00424 } 00425 #endif 00426 00427 //be careful: has no locking and parameter checks 00428 inline bool CAFirstMixChannelList::isTimedOut_internal(fmHashTableEntry* pHashTableEntry) 00429 { 00430 return (pHashTableEntry->list_TimeoutHashEntries.timoutSecs <= time(NULL)); 00431 } 00432 00433 inline bool CAFirstMixChannelList::isKickoutForced_internal(fmHashTableEntry* pHashTableEntry) 00434 { 00435 return !(pHashTableEntry->bRecoverTimeout); 00436 } 00437 00438 void CAFirstMixChannelList::setKickoutForced_internal(fmHashTableEntry* pHashTableEntry, bool kickoutForced) 00439 { 00440 if(!pHashTableEntry->bRecoverTimeout && !kickoutForced ) 00441 { 00442 CAMsg::printMsg(LOG_WARNING, "Try to switch back from forced kickout. A forced kickout cannot be undone!\n"); 00443 } 00444 else 00445 { 00446 pHashTableEntry->bRecoverTimeout = !kickoutForced; 00447 } 00448 00449 } 00450 00451 fmHashTableEntry* CAFirstMixChannelList::popTimeoutEntry_internal(bool a_bForce) 00452 { 00453 fmHashTableEntry* pHashTableEntry; 00454 00455 if (m_listTimoutHead == NULL) 00456 { 00457 // there are not entries in the list 00458 return NULL; 00459 } 00460 00461 pHashTableEntry = m_listTimoutHead; 00462 if (a_bForce || isTimedOut_internal(pHashTableEntry)) 00463 { 00464 if (removeFromTimeoutList(pHashTableEntry) == E_SUCCESS) 00465 { 00466 return pHashTableEntry; 00467 } 00468 else 00469 { 00470 CAMsg::printMsg(LOG_CRIT, 00471 "CAFirstMixChannelList:popTimeoutEntry_internal: Could not remove expired entry from timeout list!\n"); 00472 } 00473 } 00474 00475 return NULL; 00476 } 00477 #endif 00478 00479 #ifdef PAYMENT 00480 SINT32 CAFirstMixChannelList::pushTimeoutEntry(fmHashTableEntry* pHashTableEntry, bool kickoutForced) 00481 { 00482 SINT32 ret; 00483 00484 m_Mutex.lock(); 00485 ret = pushTimeoutEntry_internal(pHashTableEntry, kickoutForced); 00486 m_Mutex.unlock(); 00487 00488 return ret; 00489 } 00490 00491 00492 UINT32 CAFirstMixChannelList::countTimeoutEntries() 00493 { 00494 fmHashTableEntry* pHashTableEntry; 00495 UINT32 count = 0; 00496 00497 for (pHashTableEntry = m_listTimoutHead; pHashTableEntry != NULL; 00498 count++, pHashTableEntry = pHashTableEntry->list_TimeoutHashEntries.next); 00499 00500 return count; 00501 } 00502 #endif 00503 00504 #ifdef PAYMENT 00505 00509 SINT32 CAFirstMixChannelList::pushTimeoutEntry_internal(fmHashTableEntry* pHashTableEntry, bool kickoutForced) 00510 { 00511 if (pHashTableEntry == NULL) 00512 { 00513 return E_UNKNOWN; 00514 } 00515 00516 00517 /*if(isKickoutForced_internal(pHashTableEntry)) 00518 { 00519 return E_SUCCESS; 00520 }*/ 00521 00522 INIT_STACK; 00523 BEGIN_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal"); 00524 00525 //CAMsg::printMsg(LOG_DEBUG,"Entries in timeout list before push: %d\n", countTimeoutEntries()); 00526 00527 pHashTableEntry->list_TimeoutHashEntries.timoutSecs = time(NULL) + EXPIRATION_TIME_SECS; 00528 00529 //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "removing from timeout list"); 00530 // remove from timeout list if needed before adding it to the end 00531 removeFromTimeoutList(pHashTableEntry); 00532 setKickoutForced_internal(pHashTableEntry, kickoutForced); 00533 if (m_listTimoutFoot == NULL) 00534 { 00535 //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "new first entry"); 00536 00537 // this is the first entry in the list 00538 pHashTableEntry->list_TimeoutHashEntries.prev = NULL; 00539 m_listTimoutHead = pHashTableEntry; 00540 } 00541 else 00542 { 00543 //SAVE_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal", "new last entry"); 00544 // this is the new last entry in the list 00545 m_listTimoutFoot->list_TimeoutHashEntries.next = pHashTableEntry; 00546 pHashTableEntry->list_TimeoutHashEntries.prev = m_listTimoutFoot; 00547 } 00548 pHashTableEntry->list_TimeoutHashEntries.next = NULL; 00549 m_listTimoutFoot = pHashTableEntry; 00550 00551 //CAMsg::printMsg(LOG_DEBUG,"Entries in timeout list after push: %d\n", countTimeoutEntries()); 00552 00553 FINISH_STACK("CAFirstMixChannelList::pushTimeoutEntry_internal"); 00554 //CAMsg::printMsg(LOG_DEBUG, "CAFirstMixA: pushed entry %x!\n", pHashTableEntry); 00555 return E_SUCCESS; 00556 00557 } 00558 #endif 00559 00560 #ifdef PAYMENT 00561 SINT32 CAFirstMixChannelList::removeFromTimeoutList(fmHashTableEntry* pHashTableEntry) 00562 { 00563 if (pHashTableEntry == NULL) 00564 { 00565 return E_UNKNOWN; 00566 } 00567 00568 //CAMsg::printMsg(LOG_DEBUG, "CAFirstMixA: removing entry %x!\n", pHashTableEntry); 00569 00570 if (m_listTimoutHead == NULL || m_listTimoutFoot == NULL) 00571 { 00572 // there is no entry in the list; therefore this entry does not need to be removed 00573 return E_SUCCESS; 00574 } 00575 00576 if (pHashTableEntry->list_TimeoutHashEntries.prev == NULL && 00577 pHashTableEntry->list_TimeoutHashEntries.next == NULL && 00578 m_listTimoutHead != pHashTableEntry) 00579 { 00580 // this entry is not in the list; it does not need to be removed 00581 return E_SUCCESS; 00582 } 00583 00584 if(m_listTimoutHead == pHashTableEntry) //if entry is the head of the connection list 00585 { 00586 if(m_listTimoutFoot == pHashTableEntry) //if entry is also the last (so the only one in the list..) 00587 { 00588 //list is now empty 00589 m_listTimoutHead = NULL; 00590 m_listTimoutFoot = NULL; 00591 } 00592 else 00593 { 00594 //remove the head of the list 00595 m_listTimoutHead = pHashTableEntry->list_TimeoutHashEntries.next; 00596 } 00597 } 00598 else 00599 { //the connection is not the head of the list 00600 if(pHashTableEntry->list_TimeoutHashEntries.next == NULL) 00601 { 00602 //the connection is the last element in the list 00603 m_listTimoutFoot = pHashTableEntry->list_TimeoutHashEntries.prev; 00604 m_listTimoutFoot->list_TimeoutHashEntries.next = NULL; 00605 } 00606 else 00607 { 00608 //it is a simple middle element 00609 if (pHashTableEntry->list_TimeoutHashEntries.prev == NULL) 00610 { 00611 CAMsg::printMsg(LOG_CRIT, "CAFirstMixChannelList:removeFromTimeoutList: No previous element!!\n"); 00612 } 00613 else 00614 { 00615 pHashTableEntry->list_TimeoutHashEntries.prev->list_TimeoutHashEntries.next = pHashTableEntry->list_TimeoutHashEntries.next; 00616 } 00617 if (pHashTableEntry->list_TimeoutHashEntries.next == NULL) 00618 { 00619 CAMsg::printMsg(LOG_CRIT, "CAFirstMixChanelList:removeFromTimeoutList: No next element!!\n"); 00620 } 00621 else 00622 { 00623 pHashTableEntry->list_TimeoutHashEntries.next->list_TimeoutHashEntries.prev = pHashTableEntry->list_TimeoutHashEntries.prev; 00624 } 00625 } 00626 } 00627 pHashTableEntry->list_TimeoutHashEntries.prev = NULL; 00628 pHashTableEntry->list_TimeoutHashEntries.next = NULL; 00629 00630 return E_SUCCESS; 00631 } 00632 #endif 00633 00640 SINT32 CAFirstMixChannelList::remove(CAMuxSocket* pMuxSocket) 00641 { 00642 if(pMuxSocket==NULL) 00643 return E_UNKNOWN; 00644 SINT32 hashkey=pMuxSocket->getHashKey(); 00645 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00646 return E_UNKNOWN; 00647 m_Mutex.lock(); 00648 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00649 if(pHashTableEntry->pMuxSocket==NULL) //this connection is not in the list 00650 { 00651 m_Mutex.unlock(); 00652 return E_UNKNOWN; 00653 } 00654 #ifdef DELAY_USERS 00655 m_pMutexDelayChannel->lock(); 00656 m_pDelayBuckets[pHashTableEntry->delayBucketID]=NULL; 00657 m_pMutexDelayChannel->unlock(); 00658 #endif 00659 pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); 00660 delete pHashTableEntry->pControlChannelDispatcher; //deletes the dispatcher and all associated control channels 00661 delete pHashTableEntry->pControlMessageQueue; 00662 pHashTableEntry->pControlChannelDispatcher = NULL; 00663 pHashTableEntry->pControlMessageQueue = NULL; 00664 if(m_listHashTableNext==pHashTableEntry) //adjust the enumeration over all connections (@see getNext()) 00665 m_listHashTableNext=pHashTableEntry->list_HashEntries.next; 00666 00667 if(pHashTableEntry->list_HashEntries.prev==NULL) //if entry is the head of the connection list 00668 { 00669 if(pHashTableEntry->list_HashEntries.next==NULL) //if entry is also the last (so the only one in the list..) 00670 { 00671 m_listHashTableHead=NULL; //list is now empty 00672 } 00673 else 00674 {//remove the head of the list 00675 m_listHashTableHead=pHashTableEntry->list_HashEntries.next; 00676 m_listHashTableHead->list_HashEntries.prev=NULL; 00677 } 00678 } 00679 else 00680 { //the connection is not the head of the list 00681 if(pHashTableEntry->list_HashEntries.next==NULL) 00682 {//the connection is the last element in the list 00683 pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=NULL; 00684 } 00685 else 00686 {//its a simple middle element 00687 pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=pHashTableEntry->list_HashEntries.next; 00688 pHashTableEntry->list_HashEntries.next->list_HashEntries.prev=pHashTableEntry->list_HashEntries.prev; 00689 } 00690 } 00691 00692 00693 #ifdef PAYMENT 00694 removeFromTimeoutList(pHashTableEntry); 00695 #endif 00696 00697 fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; 00698 fmChannelListEntry* pTmpEntry; 00699 while(pEntry!=NULL)//for all channels.... 00700 { 00701 //remove the out channel form the out channel hast table 00702 hashkey=pEntry->channelOut&0x0000FFFF; 00703 pTmpEntry=m_HashTableOutChannels[hashkey]; 00704 while(pTmpEntry!=NULL) 00705 { 00706 if(pTmpEntry->channelOut==pEntry->channelOut) 00707 {//we have found the entry 00708 if(pTmpEntry->list_OutChannelHashTable.prev==NULL) //it's the head 00709 { 00710 if(pTmpEntry->list_OutChannelHashTable.next==NULL) 00711 {//it's also the last Element 00712 m_HashTableOutChannels[hashkey]=NULL; //empty this hash bucket 00713 } 00714 else 00715 { 00716 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; 00717 m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; 00718 } 00719 } 00720 else 00721 {//not the head 00722 if(pTmpEntry->list_OutChannelHashTable.next==NULL) 00723 {//but the last 00724 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; 00725 } 00726 else 00727 {//a middle element 00728 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; 00729 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; 00730 } 00731 } 00732 break; 00733 } 00734 pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; 00735 } 00736 00737 pTmpEntry=pEntry->list_InChannelPerSocket.next; 00738 #ifndef DO_TRACE 00739 delete pEntry; 00740 pEntry = NULL; 00741 #else 00742 deleteChannelListEntry(pEntry); 00743 #endif 00744 pEntry=pTmpEntry; 00745 } 00746 /* already done by pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); 00747 #ifdef PAYMENT 00748 // cleanup accounting information 00749 CAAccountingInstance::cleanupTableEntry(pHashTableEntry); 00750 #endif 00751 */ 00752 #ifdef LOG_DIALOG 00753 delete[] pHashTableEntry->strDialog; 00754 pHashTableEntry->strDialog = NULL; 00755 #endif 00756 #ifdef PAYMENT 00757 CAConditionVariable *rescue = pHashTableEntry->cleanupNotifier; 00758 #endif 00759 //TODO: a bit more precise reference cleanup 00760 memset(pHashTableEntry,0,sizeof(fmHashTableEntry)); //'delete' the connection from the connection hash table 00761 00762 #ifdef PAYMENT 00763 pHashTableEntry->cleanupNotifier = rescue; 00764 pHashTableEntry->cleanupNotifier->lock(); 00765 pHashTableEntry->cleanupNotifier->signal(); 00766 pHashTableEntry->cleanupNotifier->unlock(); 00767 #endif 00768 m_Mutex.unlock(); 00769 return E_SUCCESS; 00770 } 00771 00772 00773 #ifdef NEW_MIX_TYPE 00774 /* some additional methods for TypeB first mixes */ 00775 00783 SINT32 CAFirstMixChannelList::removeClientPart(CAMuxSocket* pMuxSocket) 00784 { 00785 if(pMuxSocket==NULL) 00786 return E_UNKNOWN; 00787 SINT32 hashkey=pMuxSocket->getSocket(); 00788 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00789 return E_UNKNOWN; 00790 m_Mutex.lock(); 00791 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00792 if(pHashTableEntry->pMuxSocket==NULL) //this connection is not in the list 00793 { 00794 m_Mutex.unlock(); 00795 return E_UNKNOWN; 00796 } 00797 #ifdef DELAY_USERS 00798 m_pMutexDelayChannel->lock(); 00799 m_pDelayBuckets[pHashTableEntry->delayBucketID]=NULL; 00800 m_pMutexDelayChannel->unlock(); 00801 #endif 00802 pHashTableEntry->pControlChannelDispatcher->deleteAllControlChannels(); 00803 delete pHashTableEntry->pControlChannelDispatcher; //deletes the dispatcher and all associated control channels 00804 pHashTableEntry->pControlChannelDispatcher = NULL; 00805 if(m_listHashTableNext==pHashTableEntry) //adjust the enumeration over all connections (@see getNext()) 00806 m_listHashTableNext=pHashTableEntry->list_HashEntries.next; 00807 00808 if(pHashTableEntry->list_HashEntries.prev==NULL) //if entry is the head of the connection list 00809 { 00810 if(pHashTableEntry->list_HashEntries.next==NULL) //if entry is also the last (so the only one in the list..) 00811 { 00812 m_listHashTableHead=NULL; //list is now empty 00813 } 00814 else 00815 {//remove the head of the list 00816 m_listHashTableHead=pHashTableEntry->list_HashEntries.next; 00817 m_listHashTableHead->list_HashEntries.prev=NULL; 00818 } 00819 } 00820 else 00821 {//the connection is not the head of the list 00822 if(pHashTableEntry->list_HashEntries.next==NULL) 00823 {//the connection is the last element in the list 00824 pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=NULL; 00825 } 00826 else 00827 {//its a simple middle element 00828 pHashTableEntry->list_HashEntries.prev->list_HashEntries.next=pHashTableEntry->list_HashEntries.next; 00829 pHashTableEntry->list_HashEntries.next->list_HashEntries.prev=pHashTableEntry->list_HashEntries.prev; 00830 } 00831 } 00832 00833 removeFromTimeoutList(pHashTableEntry); 00834 00835 00836 fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; 00837 while(pEntry!=NULL)//for all channels.... 00838 { 00839 /* leave a dummy-entry in the out-channels-table until we receive a 00840 * CLOSE-message for the channel from the last mix (else we could 00841 * re-use it, while the last mix is still using the old channel), 00842 * therefore set the the pointer for the in-channel-part to NULL 00843 */ 00844 pEntry->pHead = NULL; 00845 pEntry = pEntry->list_InChannelPerSocket.next; 00846 } 00847 #ifdef PAYMENT 00848 // cleanup accounting information 00849 CAAccountingInstance::cleanupTableEntry(pHashTableEntry); 00850 #endif 00851 memset(pHashTableEntry,0,sizeof(fmHashTableEntry)); //'delete' the connection from the connection hash table 00852 m_Mutex.unlock(); 00853 return E_SUCCESS; 00854 } 00855 00861 void CAFirstMixChannelList::removeVacantOutChannel(fmChannelListEntry* pEntry) { 00862 if (pEntry != NULL) { 00863 if (pEntry->pHead == NULL) { 00864 /* must be a vacant channel */ 00865 m_Mutex.lock(); 00866 fmChannelListEntry* pTmpEntry; 00867 /* check whether the enty is in the out-channel-table */ 00868 SINT32 hashkey = pEntry->channelOut & 0x0000FFFF; 00869 pTmpEntry = m_HashTableOutChannels[hashkey]; 00870 while (pTmpEntry != NULL) { 00871 if (pTmpEntry->channelOut == pEntry->channelOut) { 00872 //we have found the entry 00873 if (pTmpEntry->list_OutChannelHashTable.prev==NULL) { //it's the head 00874 if (pTmpEntry->list_OutChannelHashTable.next==NULL) { 00875 //it's also the last Element 00876 m_HashTableOutChannels[hashkey] = NULL; //empty this hash bucket 00877 } 00878 else { 00879 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; 00880 m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; 00881 } 00882 } 00883 else { 00884 //not the head 00885 if (pTmpEntry->list_OutChannelHashTable.next==NULL) { 00886 //but the last 00887 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; 00888 } 00889 else { 00890 //a middle element 00891 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; 00892 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; 00893 } 00894 } 00895 break; 00896 } 00897 pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; 00898 } 00899 /* entry is not in the table any more */ 00900 #ifndef DO_TRACE 00901 delete pEntry; 00902 pEntry = NULL; 00903 #else 00904 deleteChannelListEntry(pEntry); 00905 #endif 00906 m_Mutex.unlock(); 00907 } 00908 } 00909 } 00910 00915 void CAFirstMixChannelList::cleanVacantOutChannels() { 00916 m_Mutex.lock(); 00917 SINT32 hashkey = 0; 00918 do { 00919 fmChannelListEntry* pTmpEntry = m_HashTableOutChannels[hashkey]; 00920 while (pTmpEntry != NULL) { 00921 if (pTmpEntry->pHead == NULL) { 00922 /* we have found a vacant channel */ 00923 if (pTmpEntry->list_OutChannelHashTable.prev==NULL) { //it's the head 00924 if (pTmpEntry->list_OutChannelHashTable.next==NULL) { 00925 //it's also the last Element 00926 m_HashTableOutChannels[hashkey] = NULL; //empty this hash bucket 00927 } 00928 else { 00929 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; 00930 m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; 00931 } 00932 } 00933 else { 00934 //not the head 00935 if (pTmpEntry->list_OutChannelHashTable.next==NULL) { 00936 //but the last 00937 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; 00938 } 00939 else { 00940 //a middle element 00941 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; 00942 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; 00943 } 00944 } 00945 /* entry is removed from the table, now delete the channel-cipher */ 00946 delete pTmpEntry->pCipher; 00947 pTmpEntry->pCipher = NULL; 00948 fmChannelListEntry* pRemoveEntry = pTmpEntry; 00949 pTmpEntry = pTmpEntry->list_OutChannelHashTable.next; 00950 /* delete the entry */ 00951 #ifndef DO_TRACE 00952 delete pRemoveEntry; 00953 pRemoveEntry = NULL; 00954 #else 00955 deleteChannelListEntry(pEntry); 00956 #endif 00957 } 00958 else { 00959 /* not a vacant channel -> try the next channel in the hashtable-line */ 00960 pTmpEntry = pTmpEntry->list_OutChannelHashTable.next; 00961 } 00962 } 00963 /* we have processed a whole line of the channel-table -> process the next 00964 * one 00965 */ 00966 hashkey = (hashkey + 1) & 0x0000FFFF; 00967 } 00968 while (hashkey != 0); 00969 /* we have processed the whole out-channel-table */ 00970 m_Mutex.unlock(); 00971 } 00972 #endif //NEW_MIX_TYPE (TypeB first mixes) 00973 00980 SINT32 CAFirstMixChannelList::removeChannel(CAMuxSocket* pMuxSocket,HCHANNEL channelIn) 00981 { 00982 if(pMuxSocket==NULL) 00983 return E_UNKNOWN; 00984 SINT32 hashkey=pMuxSocket->getHashKey(); 00985 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 00986 return E_UNKNOWN; 00987 m_Mutex.lock(); 00988 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 00989 if(pHashTableEntry->pMuxSocket==NULL) 00990 { 00991 m_Mutex.unlock(); 00992 return E_UNKNOWN; 00993 } 00994 fmChannelListEntry* pEntry=pHashTableEntry->pChannelList; 00995 while(pEntry!=NULL) 00996 { 00997 if(pEntry->channelIn==channelIn) //search for the channel 00998 { 00999 hashkey=pEntry->channelOut&0x0000FFFF; //remove the out channel from the out channel hash table 01000 fmChannelListEntry*pTmpEntry=m_HashTableOutChannels[hashkey]; 01001 while(pTmpEntry!=NULL) 01002 { 01003 if(pTmpEntry->channelOut==pEntry->channelOut) 01004 {//found it in the out channel hash table 01005 if(pTmpEntry->list_OutChannelHashTable.prev==NULL) //head 01006 { 01007 if(pTmpEntry->list_OutChannelHashTable.next==NULL) 01008 { 01009 m_HashTableOutChannels[hashkey]=NULL; 01010 } 01011 else 01012 { 01013 01014 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=NULL; 01015 m_HashTableOutChannels[hashkey]=pTmpEntry->list_OutChannelHashTable.next; 01016 } 01017 } 01018 else 01019 { 01020 if(pTmpEntry->list_OutChannelHashTable.next==NULL) 01021 {//last element 01022 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=NULL; 01023 } 01024 else 01025 {//middle element 01026 pTmpEntry->list_OutChannelHashTable.prev->list_OutChannelHashTable.next=pTmpEntry->list_OutChannelHashTable.next; 01027 pTmpEntry->list_OutChannelHashTable.next->list_OutChannelHashTable.prev=pTmpEntry->list_OutChannelHashTable.prev; 01028 } 01029 } 01030 break; 01031 } 01032 pTmpEntry=pTmpEntry->list_OutChannelHashTable.next; 01033 } 01034 01035 //remove the channel from the channel hast table 01036 if(pEntry->list_InChannelPerSocket.prev==NULL) //head 01037 { 01038 if(pEntry->list_InChannelPerSocket.next==NULL) 01039 {//the only element 01040 pHashTableEntry->pChannelList=NULL; 01041 } 01042 else 01043 { 01044 pEntry->list_InChannelPerSocket.next->list_InChannelPerSocket.prev=NULL; 01045 pHashTableEntry->pChannelList=pEntry->list_InChannelPerSocket.next; 01046 } 01047 } 01048 else 01049 { 01050 if(pEntry->list_InChannelPerSocket.next==NULL) 01051 {//the last element 01052 pEntry->list_InChannelPerSocket.prev->list_InChannelPerSocket.next=NULL; 01053 } 01054 else 01055 {//a middle element 01056 pEntry->list_InChannelPerSocket.prev->list_InChannelPerSocket.next=pEntry->list_InChannelPerSocket.next; 01057 pEntry->list_InChannelPerSocket.next->list_InChannelPerSocket.prev=pEntry->list_InChannelPerSocket.prev; 01058 } 01059 } 01060 #ifndef DO_TRACE 01061 delete pEntry; 01062 pEntry = NULL; 01063 #else 01064 deleteChannelListEntry(pEntry); 01065 #endif 01066 pHashTableEntry->cNumberOfChannels--; 01067 m_Mutex.unlock(); 01068 return E_SUCCESS; 01069 } 01070 pEntry=pEntry->list_InChannelPerSocket.next; //try next channel 01071 } 01072 m_Mutex.unlock(); 01073 return E_UNKNOWN;//not found 01074 } 01075 01081 fmHashTableEntry* CAFirstMixChannelList::getFirst() 01082 { 01083 m_Mutex.lock(); 01084 if(m_listHashTableHead!=NULL) 01085 m_listHashTableNext=m_listHashTableHead->list_HashEntries.next; 01086 else 01087 m_listHashTableNext=NULL; 01088 m_Mutex.unlock(); 01089 return m_listHashTableHead; 01090 } 01091 01097 fmHashTableEntry* CAFirstMixChannelList::getNext() 01098 { 01099 m_Mutex.lock(); 01100 fmHashTableEntry* tmpEntry=m_listHashTableNext; 01101 if(m_listHashTableNext!=NULL) 01102 m_listHashTableNext=m_listHashTableNext->list_HashEntries.next; 01103 m_Mutex.unlock(); 01104 return tmpEntry; 01105 } 01106 01113 fmChannelListEntry* CAFirstMixChannelList::getFirstChannelForSocket(CAMuxSocket* pMuxSocket) 01114 { 01115 if(pMuxSocket==NULL) 01116 return NULL; 01117 SINT32 hashkey=pMuxSocket->getHashKey(); 01118 if(hashkey>MAX_HASH_KEY-1||hashkey<0) 01119 return NULL; 01120 fmHashTableEntry* pHashTableEntry=m_HashTable[hashkey]; 01121 return pHashTableEntry->pChannelList; 01122 } 01123 01130 fmChannelListEntry* CAFirstMixChannelList::getNextChannel(fmChannelListEntry* pEntry) 01131 { 01132 if(pEntry==NULL) 01133 return NULL; 01134 return pEntry->list_InChannelPerSocket.next; 01135 } 01136 01137 SINT32 CAFirstMixChannelList::test() 01138 { 01139 CAFirstMixChannelList* pList=new CAFirstMixChannelList(); 01140 CAMuxSocket *pMuxSocket=new CAMuxSocket(); 01141 pMuxSocket->getCASocket()->create(); 01142 UINT8 peerIP[4]; 01143 #ifndef LOG_DIALOG 01144 pList->add(pMuxSocket,peerIP,NULL,NULL,NULL); 01145 #else 01146 pList->add(pMuxSocket,peerIP,NULL,(UINT8*)"1"); 01147 #endif 01148 #if defined(HAVE_CRTDBG) 01149 _CrtMemState s1, s2, s3; 01150 _CrtMemCheckpoint( &s1 ); 01151 #endif 01152 UINT32 /*channelIn,*/i,channelOut; 01153 for(i=0;i<50;i++) 01154 pList->addChannel(pMuxSocket,i,NULL,&channelOut); 01155 for(i=0;i<50;i++) 01156 pList->removeChannel(pMuxSocket,i); 01157 #if defined(HAVE_CRTDBG) 01158 _CrtMemCheckpoint( &s2 ); 01159 if ( _CrtMemDifference( &s3, &s1, &s2 ) ) 01160 _CrtMemDumpStatistics( &s3 ); 01161 #endif 01162 01163 pList->remove(pMuxSocket); 01164 delete pMuxSocket; 01165 pMuxSocket = NULL; 01166 delete pList; 01167 pList = NULL; 01168 return E_SUCCESS; 01169 } 01170 01171 #ifdef DELAY_USERS 01172 THREAD_RETURN fml_loopDelayBuckets(void* param) 01173 { 01174 INIT_STACK; 01175 BEGIN_STACK("CAFirstMixChannelList::fml_loopDelayBuckets"); 01176 01177 CAFirstMixChannelList* pChannelList=(CAFirstMixChannelList*)param; 01178 volatile UINT32** pDelayBuckets=pChannelList->m_pDelayBuckets; 01179 while(pChannelList->m_bDelayBucketsLoopRun) 01180 { 01181 pChannelList->m_pMutexDelayChannel->lock(); 01182 UINT32 u32BucketGrow=pChannelList->m_u32DelayChannelBucketGrow; 01183 UINT32 u32MaxBucket=u32BucketGrow*10; 01184 for(UINT32 i=0;i<MAX_POLLFD;i++) 01185 { 01186 if(pDelayBuckets[i]!=NULL&&*(pDelayBuckets[i])<u32MaxBucket) 01187 { 01188 *(pDelayBuckets[i])+=u32BucketGrow; 01189 } 01190 } 01191 pChannelList->m_pMutexDelayChannel->unlock(); 01192 msSleep(pChannelList->m_u32DelayChannelBucketGrowIntervall); 01193 } 01194 01195 FINISH_STACK("CAFirstMixChannelList::fml_loopDelayBuckets"); 01196 01197 THREAD_RETURN_SUCCESS; 01198 } 01199 01200 void CAFirstMixChannelList::decDelayBuckets(UINT32 delayBucketID) 01201 { 01202 m_pMutexDelayChannel->lock(); 01203 if(delayBucketID < MAX_POLLFD) 01204 { 01205 if(m_pDelayBuckets[delayBucketID] != NULL) 01206 { 01207 *(m_pDelayBuckets[delayBucketID]) -= ( (*(m_pDelayBuckets[delayBucketID])) > 0 ) ? 1 : 0; 01208 } 01209 /*CAMsg::printMsg(LOG_DEBUG,"DelayBuckets decrementing ID %u downto %u\n", 01210 delayBucketID, (*(m_pDelayBuckets[delayBucketID])) );*/ 01211 } 01212 m_pMutexDelayChannel->unlock(); 01213 } 01214 01215 bool CAFirstMixChannelList::hasDelayBuckets(UINT32 delayBucketID) 01216 { 01217 bool ret = false; 01218 m_pMutexDelayChannel->lock(); 01219 if(delayBucketID < MAX_POLLFD) 01220 { 01221 if(m_pDelayBuckets[delayBucketID] != NULL) 01222 { 01223 ret = ( (*(m_pDelayBuckets[delayBucketID])) > 0 ); 01224 } 01225 } 01226 m_pMutexDelayChannel->unlock(); 01227 return ret; 01228 } 01229 01230 void CAFirstMixChannelList::setDelayParameters(UINT32 unlimitTraffic,UINT32 bucketGrow,UINT32 intervall) 01231 { 01232 m_pMutexDelayChannel->lock(); 01233 CAMsg::printMsg(LOG_DEBUG,"CAFirstMixChannelList - Set new traffic limit per user- unlimit: %u bucketgrow: %u intervall %u\n", 01234 unlimitTraffic,bucketGrow,intervall); 01235 m_u32DelayChannelUnlimitTraffic=unlimitTraffic; 01236 m_u32DelayChannelBucketGrow=bucketGrow; 01237 m_u32DelayChannelBucketGrowIntervall=intervall; 01238 for(UINT32 i=0;i<MAX_POLLFD;i++) 01239 if(m_pDelayBuckets[i]!=NULL) 01240 *(m_pDelayBuckets[i])=m_u32DelayChannelUnlimitTraffic; 01241 m_pMutexDelayChannel->unlock(); 01242 } 01243 01244 #endif 01245 #endif //ONLY_LOCAL_PROXY
1.7.6.1