Mixe for Privacy and Anonymity in the Internet
CAChainTable.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2006, The JAP-Team
3  * All rights reserved.
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * - Redistributions of source code must retain the above copyright notice,
8  * this list of conditions and the following disclaimer.
9  *
10  * - Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * - Neither the name of the University of Technology Dresden, Germany nor
15  * the names of its contributors may be used to endorse or promote
16  * products derived from this software without specific prior written
17  * permission.
18  *
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
24  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE
31  */
32 #include "../StdAfx.h"
33 #ifndef ONLY_LOCAL_PROXY
34 #include "CAChainTable.hpp"
35 #include "typedefsb.hpp"
36 #include "../CAUtil.hpp"
37 
38 
40  m_pChainTable = new (t_chaintableEntry*[0x10000]);
41  for (UINT32 i = 0; i < 0x10000; i++) {
42  m_pChainTable[i] = NULL;
43  }
44  m_pMutex = new CAMutex();
45  m_chaintableSize = 0;
46  m_pChaintableIterator = NULL;
47  #ifdef DELAY_CHANNELS
48  m_initialBucketSize = DELAY_CHANNEL_TRAFFIC;
49  m_delayBucketGrow = DELAY_BUCKET_GROW;
50  m_delayBucketGrowInterval = DELAY_BUCKET_GROW_INTERVALL;
51  m_pDelayBucketMutex = new CAMutex();
52  m_pDelayBuckets = new SINT32[MAX_POLLFD];
53  for (UINT32 i = 0; i < MAX_POLLFD; i++) {
54  m_pDelayBuckets[i] = -1;
55  }
56  /* start the delay-buckets-refill loop */
57  m_delayBucketsLoopRun = true;
58  m_pDelayBucketsLoop = new CAThread((UINT8*)"CAChainTable: delay-buckets refill thread");
59  m_pDelayBucketsLoop->setMainLoop(lml_chaintableDelayBucketsLoop);
60  m_pDelayBucketsLoop->start(this);
61  #endif
62 }
63 
65  /* use the iterator to clean the table */
66  getFirstEntry();
67  while (m_pChaintableIterator != NULL) {
68  /* chaintable iterator is removed, if last entry is reached */
70  /* entry is removed automatically, when the iterator points to the next
71  * entry
72  */
73  getNextEntry();
74  }
75  #ifdef DELAY_CHANNELS
76  m_delayBucketsLoopRun = false;
77  /* wait for the delay-buckets-refill loop */
78  m_pDelayBucketsLoop->join();
79  delete m_pDelayBucketsLoop;
80  m_pDelayBucketsLoop = NULL;
81  delete m_pDelayBucketMutex;
82  m_pDelayBucketMutex = NULL;
83  delete []m_pDelayBuckets;
84  m_pDelayBuckets = NULL;
85  #endif
86  delete m_pMutex;
87  m_pMutex = NULL;
88  delete []m_pChainTable;
89  m_pChainTable = NULL;
90 }
91 
93  m_pMutex->lock();
94  CAChain* returnedChain = NULL;
95  t_chaintableEntry* chaintableEntry = getEntryInternal(a_chainId);
96  if (chaintableEntry != NULL) {
97  returnedChain = chaintableEntry->chain;
98  }
99  m_pMutex->unlock();
100  return returnedChain;
101 }
102 
104  m_pMutex->lock();
105  t_chaintableEntry* chaintableEntry = getEntryInternal(a_chainId);
106  if (chaintableEntry != NULL) {
107  /* we have found an entry with the specified ID -> check whether the
108  * iterator points to it
109  */
110  if (m_pChaintableIterator != NULL) {
111  if (m_pChaintableIterator->currentEntry == chaintableEntry) {
112  /* don't remove the entry but set the remove-flag for the iterator */
114  }
115  else {
116  removeEntryInternal(chaintableEntry);
117  }
118  }
119  else {
120  removeEntryInternal(chaintableEntry);
121  }
122  }
123  m_pMutex->unlock();
124 }
125 
127  CAChain* firstChain = NULL;
128  m_pMutex->lock();
129  if (m_pChaintableIterator == NULL) {
131  }
132  else {
133  /* look whether we shall remove our last entry */
136  }
137  }
142  if (m_pChaintableIterator->currentEntry == NULL) {
143  /* no entries in the table */
144  delete m_pChaintableIterator;
145  m_pChaintableIterator = NULL;
146  }
147  else {
149  }
150  m_pMutex->unlock();
151  return firstChain;
152 }
153 
155  CAChain* nextChain = NULL;
156  m_pMutex->lock();
157  if (m_pChaintableIterator != NULL) {
159  if (m_pChaintableIterator->currentEntry == NULL) {
160  /* no more entries in the table */
161  delete m_pChaintableIterator;
162  m_pChaintableIterator = NULL;
163  }
164  else {
166  }
167  }
168  m_pMutex->unlock();
169  return nextChain;
170 }
171 
173  m_pMutex->lock();
174  if (m_chaintableSize >= MAX_POLLFD) {
175  /* we cannot create more chains because we are not able to handle more
176  * sockets
177  */
178  m_pMutex->unlock();
179  return NULL;
180  }
181  /* create a unique chain-id */
183  do {
185  m_pMutex->unlock();
186  delete []chainId;
187  chainId = NULL;
188  return NULL;
189  }
190  }
191  while (getEntryInternal(chainId) != NULL);
192  t_chaintableEntry* newEntry = new t_chaintableEntry;
193  #ifndef DELAY_CHANNELS
194  newEntry->chain = new CAChain(chainId);
195  #else
196  /* find an unused delay-bucket */
197  m_pDelayBucketMutex->lock();
198  UINT32 i = 0;
199  bool bucketFound = false;
200  while ((!bucketFound) && (i < MAX_POLLFD)) {
201  if (m_pDelayBuckets[i] == -1) {
202  bucketFound = true;
203  }
204  else {
205  i++;
206  }
207  }
208  if (!bucketFound) {
209  /* we found no bucket -> this shouldn't happen because there cannot be
210  * more chains than buckets
211  */
212  m_pDelayBucketMutex->unlock();
213  delete newEntry;
214  newEntry = NULL;
215  delete []chainId;
216  chainId = NULL;
217  m_pMutex->unlock();
218  return NULL;
219  }
220  /* initalize our bucket */
221  m_pDelayBuckets[i] = (SINT32)m_initialBucketSize;
222  m_pDelayBucketMutex->unlock();
223  newEntry->chain = new CAChain(chainId, m_pDelayBucketMutex, &(m_pDelayBuckets[i]));
224  #endif
225  /* take the lower 16 bits as key for the hashtable */
226  UINT16 hashKey = (((UINT16)(chainId[CHAIN_ID_LENGTH - 2])) << 8) | (UINT16)(chainId[CHAIN_ID_LENGTH - 1]);
227  /* now add the entry at the begin of the hashtable-line */
228  newEntry->rightEntry = m_pChainTable[hashKey];
229  newEntry->rightEntryPointerOfLeftEntry = &(m_pChainTable[hashKey]);
230  m_pChainTable[hashKey] = newEntry;
231  if (newEntry->rightEntry != NULL) {
232  newEntry->rightEntry->rightEntryPointerOfLeftEntry = &(newEntry->rightEntry);
233  }
235  m_pMutex->unlock();
236  return (newEntry->chain);
237 }
238 
240  UINT32 chaintableSize;
241  m_pMutex->lock();
242  chaintableSize = m_chaintableSize;
243  m_pMutex->unlock();
244  return chaintableSize;
245 }
246 
247 
249  /* mutex must be already locked */
250  /* take the lower 16 bits as key for the hashtable */
251  UINT16 hashKey = (((UINT16)(a_chainId[CHAIN_ID_LENGTH - 2])) << 8) | (UINT16)(a_chainId[CHAIN_ID_LENGTH - 1]);
252  bool entryFound = false;
253  t_chaintableEntry* currentEntry = m_pChainTable[hashKey];
254  while ((currentEntry != NULL) && !entryFound) {
255  /* a removed entry could be in the table, if the iterator points to it ->
256  * we have to check it
257  */
258  bool entryVirtualRemoved = false;
259  if (m_pChaintableIterator != NULL) {
261  entryVirtualRemoved = true;
262  /* skip this entry */
263  currentEntry = currentEntry->rightEntry;
264  }
265  }
266  if (!entryVirtualRemoved) {
267  /* compare the Chain-IDs (lower 2 bytes are identical because of the same
268  * hashkey -> don't compare them)
269  */
270  if (memcmp(currentEntry->chain->getChainId(), a_chainId, CHAIN_ID_LENGTH - 2) == 0) {
271  /* we have found the entry */
272  entryFound = true;
273  }
274  else {
275  currentEntry = currentEntry->rightEntry;
276  }
277  }
278  }
279  return currentEntry;
280 }
281 
283  /* mutex must be already locked */
284  *(a_entry->rightEntryPointerOfLeftEntry) = a_entry->rightEntry;
285  if (a_entry->rightEntry != NULL) {
287  }
288  /* delete the chain */
289  delete a_entry->chain;
290  a_entry->chain = NULL;
291  /* delete the table-entry */
292  delete a_entry;
293  a_entry = NULL;
295 }
296 
298  /* mutex must be already locked */
299  t_chaintableEntry* nextEntry;
300  if (a_iterator->currentEntry == NULL) {
301  nextEntry = NULL;
302  }
303  else {
304  nextEntry = a_iterator->currentEntry->rightEntry;
305  /* look whether we shall remove our last entry */
306  if (a_iterator->removeEntry) {
307  removeEntryInternal(a_iterator->currentEntry);
308  a_iterator->removeEntry = false;
309  }
310  }
311  if (nextEntry == NULL) {
312  /* we have to start at the current hashtable-line until we find a
313  * hashtable-line with entries or reach again the top of the table
314  */
315  do {
316  a_iterator->currentEntry = m_pChainTable[a_iterator->nextHashkey];
317  (a_iterator->nextHashkey)++;
318  }
319  while ((a_iterator->currentEntry == NULL) && (a_iterator->nextHashkey != 0));
320  if (a_iterator->nextHashkey == 0) {
321  /* we have reached the top of the table again */
322  a_iterator->currentEntry = NULL;
323  }
324  }
325  else {
326  /* we have another entry in the same hashtable-line */
327  a_iterator->currentEntry = nextEntry;
328  }
329 }
330 
331 #ifdef DELAY_CHANNELS
332  THREAD_RETURN lml_chaintableDelayBucketsLoop(void* a_param) {
333  /* get the chaintable we are running on from the parameter */
334  CAChainTable* pChainTable = (CAChainTable*)a_param;
335  while (pChainTable->m_delayBucketsLoopRun) {
336  pChainTable->m_pDelayBucketMutex->lock();
337  SINT32 bucketGrow = (SINT32)(pChainTable->m_delayBucketGrow);
338  for (UINT32 i = 0; i < MAX_POLLFD; i++) {
339  if ((pChainTable->m_pDelayBuckets[i]) != -1) {
340  /* let only grow used buckets, but don't make them too large */
341  pChainTable->m_pDelayBuckets[i] = min((pChainTable->m_pDelayBuckets[i]) + bucketGrow, MAX_DELAY_BUCKET_SIZE);
342  }
343  }
344  pChainTable->m_pDelayBucketMutex->unlock();
345  /* sleep some time before the next grow-round starts */
346  msSleep((UINT16)(pChainTable->m_delayBucketGrowInterval));
347  }
349  }
350 
351  void CAChainTable::setDelayParameters(UINT32 a_initialBucketSize, UINT32 a_delayBucketGrow, UINT32 a_delayBucketGrowInterval) {
352  CAMsg::printMsg(LOG_DEBUG, "CAChainTable - Set new traffic limit per channel: inital size: %u bucket grow: %u interval: %u\n", a_initialBucketSize, a_delayBucketGrow, a_delayBucketGrowInterval);
353  m_pDelayBucketMutex->lock();
354  m_initialBucketSize = a_initialBucketSize;
355  m_delayBucketGrow = a_delayBucketGrow;
356  m_delayBucketGrowInterval = a_delayBucketGrowInterval;
357  /* re-initialize all used buckets */
358  for (UINT32 i = 0; i < MAX_POLLFD; i++) {
359  if (m_pDelayBuckets[i] != -1) {
360  /* re-initialize only used buckets */
361  m_pDelayBuckets[i] = a_initialBucketSize;
362  }
363  }
364  m_pDelayBucketMutex->unlock();
365  }
366 #endif //DELAY_CHANNELS
367 #endif//onlyLOCAL_PROXY
SINT32 getRandom(UINT32 *val)
Gets 32 random bits.
Definition: CAUtil.cpp:346
SINT32 msSleep(UINT32 ms)
Sleeps ms milliseconds.
Definition: CAUtil.cpp:406
#define THREAD_RETURN
Definition: StdAfx.h:540
#define THREAD_RETURN_SUCCESS
Definition: StdAfx.h:542
#define min(a, b)
Definition: StdAfx.h:649
#define MAX_POLLFD
Definition: StdAfx.h:192
unsigned short UINT16
Definition: basetypedefs.h:133
signed int SINT32
Definition: basetypedefs.h:132
unsigned char UINT8
Definition: basetypedefs.h:135
unsigned int UINT32
Definition: basetypedefs.h:131
UINT8 * getChainId()
Definition: CAChain.cpp:123
CAChain * getNextEntry()
t_chaintableIterator * m_pChaintableIterator
CAMutex * m_pMutex
UINT32 m_chaintableSize
CAChain * getFirstEntry()
UINT32 getSize()
CAChainTable(void)
CAChain * createEntry()
~CAChainTable(void)
CAChain * getEntry(UINT8 *a_chainId)
void getNextEntryInternal(t_chaintableIterator *a_iterator)
t_chaintableEntry ** m_pChainTable
t_chaintableEntry * getEntryInternal(UINT8 *a_chainId)
void removeEntryInternal(t_chaintableEntry *a_entry)
void deleteEntry(UINT8 *a_chainId)
static SINT32 printMsg(UINT32 typ, const char *format,...)
Writes a given message to the log.
Definition: CAMsg.cpp:251
SINT32 unlock()
Definition: CAMutex.hpp:52
SINT32 lock()
Definition: CAMutex.hpp:41
const SINT32 E_SUCCESS
Definition: errorcodes.hpp:2
CAChain * chain
t_chaintableEntry * rightEntry
t_chaintableEntry ** rightEntryPointerOfLeftEntry
t_chaintableEntry * currentEntry
UINT8 chainId[CHAIN_ID_LENGTH]
Definition: typedefsb.hpp:0
#define CHAIN_ID_LENGTH
Definition: typedefsb.hpp:40