1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2005-2011 aMule Team ( admin@amule.org / http://www.amule.org )
5 // Copyright (c) 2002-2011 Merkur ( devs@emule-project.net / http://www.emule-project.net )
6 //
7 // Any parts of this program derived from the xMule, lMule or eMule project,
8 // or contributed by third-party developers are copyrighted by their
9 // respective authors.
10 //
11 // This program is free software; you can redistribute it and/or modify
12 // it under the terms of the GNU General Public License as published by
13 // the Free Software Foundation; either version 2 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful,
17 // but WITHOUT ANY WARRANTY; without even the implied warranty of
18 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 // GNU General Public License for more details.
20 //
21 // You should have received a copy of the GNU General Public License
22 // along with this program; if not, write to the Free Software
23 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA
24 //
25 
26 #include "DeadSourceList.h"
27 
28 #include <common/Macros.h>
29 
30 #include "updownclient.h"		// Needed for CUpDownClient
31 
32 #define	CLEANUPTIME			MIN2MS(60)
33 
34 #define BLOCKTIME		(::GetTickCount() + (m_bGlobalList ? MIN2MS(30) : MIN2MS(45)))
35 #define BLOCKTIMEFW		(::GetTickCount() + (m_bGlobalList ? MIN2MS(45) : MIN2MS(60)))
36 
37 ///////////////////////////////////////////////////////////////////////////////////////
38 //// CDeadSource
39 
40 
CDeadSource(uint32 ID,uint16 Port,uint32 ServerIP,uint16 KadPort)41 CDeadSourceList::CDeadSource::CDeadSource(uint32 ID, uint16 Port, uint32 ServerIP, uint16 KadPort)
42 {
43 	m_ID = ID;
44 	m_Port = Port;
45 	m_KadPort = KadPort;
46 	m_ServerIP = ServerIP;
47 	m_TimeStamp = 0;
48 }
49 
50 
SetTimeout(uint32 t)51 void CDeadSourceList::CDeadSource::SetTimeout( uint32 t )
52 {
53 	m_TimeStamp = t;
54 }
55 
56 
GetTimeout() const57 uint32 CDeadSourceList::CDeadSource::GetTimeout() const
58 {
59 	return m_TimeStamp;
60 }
61 
62 
operator ==(const CDeadSource & other) const63 bool CDeadSourceList::CDeadSource::operator==(const CDeadSource& other) const
64 {
65 	if ( m_ID == other.m_ID ) {
66 		if ( m_Port == other.m_Port || m_KadPort == other.m_KadPort ) {
67 			if ( IsLowID( m_ID ) ) {
68 				return m_ServerIP == other.m_ServerIP;
69 			} else {
70 				return true;
71 			}
72 		}
73 	}
74 
75 	return false;
76 }
77 
78 
79 ///////////////////////////////////////////////////////////////////////////////////////
80 //// CDeadSourceList
81 
CDeadSourceList(bool isGlobal)82 CDeadSourceList::CDeadSourceList(bool isGlobal)
83 {
84 	m_dwLastCleanUp = ::GetTickCount();
85 	m_bGlobalList = isGlobal;
86 }
87 
88 
GetDeadSourcesCount() const89 uint32 CDeadSourceList::GetDeadSourcesCount() const
90 {
91 	return m_sources.size();
92 }
93 
94 
IsDeadSource(const CUpDownClient * client)95 bool CDeadSourceList::IsDeadSource(const CUpDownClient* client)
96 {
97 	CDeadSource source(
98 		client->GetUserIDHybrid(),
99 		client->GetUserPort(),
100 		client->GetServerIP(),
101 		client->GetKadPort()
102 	);
103 
104 
105 	DeadSourcePair range = m_sources.equal_range( client->GetUserIDHybrid() );
106 	for ( ; range.first != range.second; range.first++ ) {
107 		if ( range.first->second == source ) {
108 			// Check if the entry is still valid
109 			if ( range.first->second.GetTimeout() > GetTickCount() ) {
110 				return true;
111 			}
112 
113 			// The source is no longer dead, so remove it to reduce the size of the list
114 			m_sources.erase( range.first );
115 			break;
116 		}
117 	}
118 
119 	return false;
120 }
121 
122 
AddDeadSource(const CUpDownClient * client)123 void CDeadSourceList::AddDeadSource( const CUpDownClient* client )
124 {
125 	CDeadSource source(
126 		client->GetUserIDHybrid(),
127 		client->GetUserPort(),
128 		client->GetServerIP(),
129 		client->GetKadPort()
130 	);
131 
132 	// Set the timeout for the new source
133 	source.SetTimeout( client->HasLowID() ? BLOCKTIMEFW : BLOCKTIME );
134 
135 	// Check if the source is already listed
136 	DeadSourcePair range = m_sources.equal_range( client->GetUserIDHybrid() );
137 	for ( ; range.first != range.second; range.first++ ) {
138 		if ( range.first->second == source ) {
139 			range.first->second = source;
140 			return;
141 		}
142 	}
143 
144 	m_sources.insert( DeadSourceMap::value_type( client->GetUserIDHybrid(), source ) );
145 
146 	// Check if we should cleanup the list. This is
147 	// done to avoid a buildup of stale entries.
148 	if ( GetTickCount() - m_dwLastCleanUp > CLEANUPTIME ) {
149 		CleanUp();
150 	}
151 }
152 
153 
CleanUp()154 void CDeadSourceList::CleanUp()
155 {
156 	m_dwLastCleanUp = ::GetTickCount();
157 
158 	DeadSourceIterator it = m_sources.begin();
159 	for ( ; it != m_sources.end(); ) {
160 		DeadSourceIterator it1 = it++;
161 		if ( it1->second.GetTimeout() < m_dwLastCleanUp ) {
162 			m_sources.erase( it1 );
163 		}
164 	}
165 }
166 // File_checked_for_headers
167