Updated changelog
[amule.git] / src / ListenSocket.cpp
blob971e1961e2f7613265405d613e4aff066b8b2fe6
1 //
2 // This file is part of the aMule Project.
3 //
4 // Copyright (c) 2003-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.
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.
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.
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
26 #include "ListenSocket.h" // Interface declarations
28 #include <common/EventIDs.h>
30 #include "ClientTCPSocket.h" // Needed for CClientRequestSocket
31 #include "Logger.h" // Needed for AddLogLineM
32 #include "Statistics.h" // Needed for theStats
33 #include "Preferences.h" // Needed for CPreferences
34 #include "amule.h" // Needed for theApp
35 #include "ServerConnect.h" // Needed for CServerConnect
37 //-----------------------------------------------------------------------------
38 // CListenSocket
39 //-----------------------------------------------------------------------------
41 // This is the socket that listens to incoming connections in aMule's TCP port
42 // As soon as a connection is detected, it creates a new socket of type
43 // CClientTCPSocket to handle (accept) the connection.
46 CListenSocket::CListenSocket(amuleIPV4Address &addr, const CProxyData *ProxyData)
48 // wxSOCKET_NOWAIT - means non-blocking i/o
49 // wxSOCKET_REUSEADDR - means we can reuse the socket immediately (wx-2.5.3)
50 CSocketServerProxy(addr, MULE_SOCKET_NOWAIT|MULE_SOCKET_REUSEADDR, ProxyData)
52 // 0.42e - vars not used by us
53 m_pending = false;
54 shutdown = false;
55 m_OpenSocketsInterval = 0;
56 totalconnectionchecks = 0;
57 averageconnections = 0.0;
58 memset(m_ConnectionStates, 0, 3 * sizeof(m_ConnectionStates[0]));
59 // Set the listen socket event handler -- The handler is written in amule.cpp
60 if (IsOk()) {
61 #ifndef ASIO_SOCKETS
62 SetEventHandler(*theApp, ID_LISTENSOCKET_EVENT);
63 SetNotify(wxSOCKET_CONNECTION_FLAG);
64 #endif
65 Notify(true);
67 AddLogLineNS(_("ListenSocket: Ok."));
68 } else {
69 AddLogLineCS(_("ERROR: Could not listen to TCP port.") );
74 CListenSocket::~CListenSocket()
76 shutdown = true;
77 Discard();
78 Close();
80 #ifdef __DEBUG__
81 // No new sockets should have been opened by now
82 for (SocketSet::iterator it = socket_list.begin(); it != socket_list.end(); ++it) {
83 wxASSERT((*it)->IsDestroying());
85 #endif
87 KillAllSockets();
91 void CListenSocket::OnAccept()
93 m_pending = theApp->IsRunning(); // just do nothing if we are shutting down
94 // If the client is still at maxconnections,
95 // this will allow it to go above it ...
96 // But if you don't, you will get a lowID on all servers.
97 while (m_pending && (theApp->serverconnect->IsConnecting() || !TooManySockets())) {
98 if (!SocketAvailable()) {
99 m_pending = false;
100 } else {
101 // Create a new socket to deal with the connection
102 CClientTCPSocket* newclient = new CClientTCPSocket();
103 // Accept the connection and give it to the newly created socket
104 if (!AcceptWith(*newclient, false)) {
105 newclient->Safe_Delete();
106 m_pending = false;
107 } else {
108 if (!newclient->InitNetworkData()) {
109 // IP or port were not returned correctly
110 // from the accepted address, or filtered.
111 newclient->Safe_Delete();
116 if (m_pending) {
117 theStats::AddMaxConnectionLimitReached();
121 void CListenSocket::AddConnection()
123 m_OpenSocketsInterval++;
126 void CListenSocket::Process()
128 // 042e + Kry changes for Destroy
129 m_OpenSocketsInterval = 0;
130 SocketSet::iterator it = socket_list.begin();
131 while ( it != socket_list.end() ) {
132 CClientTCPSocket* cur_socket = *it++;
133 if (!cur_socket->IsDestroying()) {
134 cur_socket->CheckTimeOut();
138 if (m_pending) {
139 OnAccept();
143 void CListenSocket::RecalculateStats()
145 // 0.42e
146 memset(m_ConnectionStates, 0, 3 * sizeof(m_ConnectionStates[0]));
147 for (SocketSet::iterator it = socket_list.begin(); it != socket_list.end(); ) {
148 CClientTCPSocket* cur_socket = *it++;
149 switch (cur_socket->GetConState()) {
150 case ES_DISCONNECTED:
151 m_ConnectionStates[0]++;
152 break;
153 case ES_NOTCONNECTED:
154 m_ConnectionStates[1]++;
155 break;
156 case ES_CONNECTED:
157 m_ConnectionStates[2]++;
158 break;
163 void CListenSocket::AddSocket(CClientTCPSocket* toadd)
165 wxASSERT(toadd);
166 socket_list.insert(toadd);
167 theStats::AddActiveConnection();
170 void CListenSocket::RemoveSocket(CClientTCPSocket* todel)
172 wxASSERT(todel);
173 socket_list.erase(todel);
174 theStats::RemoveActiveConnection();
177 void CListenSocket::KillAllSockets()
179 // 0.42e reviewed - they use delete, but our safer is Destroy...
180 // But I bet it would be better to call Safe_Delete on the socket.
181 // Update: no... Safe_Delete MARKS for deletion. We need to delete it.
182 for (SocketSet::iterator it = socket_list.begin(); it != socket_list.end(); ) {
183 CClientTCPSocket* cur_socket = *it++;
184 if (cur_socket->GetClient()) {
185 cur_socket->Safe_Delete_Client();
186 } else {
187 cur_socket->Safe_Delete();
188 cur_socket->Destroy();
193 bool CListenSocket::TooManySockets(bool bIgnoreInterval)
195 if (GetOpenSockets() > thePrefs::GetMaxConnections()
196 || (!bIgnoreInterval && m_OpenSocketsInterval > (thePrefs::GetMaxConperFive() * GetMaxConperFiveModifier()))) {
197 return true;
198 } else {
199 return false;
203 bool CListenSocket::IsValidSocket(CClientTCPSocket* totest)
205 // 0.42e
206 return socket_list.find(totest) != socket_list.end();
210 void CListenSocket::UpdateConnectionsStatus()
212 // 0.42e xcept for the khaos stats
213 if( theApp->IsConnected() ) {
214 totalconnectionchecks++;
215 float percent;
216 percent = (float)(totalconnectionchecks-1)/(float)totalconnectionchecks;
217 if( percent > .99f ) {
218 percent = .99f;
220 averageconnections = (averageconnections*percent) + (float)GetOpenSockets()*(1.0f-percent);
225 float CListenSocket::GetMaxConperFiveModifier()
227 float SpikeSize = GetOpenSockets() - averageconnections;
228 if ( SpikeSize < 1 ) {
229 return 1;
232 float SpikeTolerance = 2.5f * thePrefs::GetMaxConperFive();
233 if ( SpikeSize > SpikeTolerance ) {
234 return 0;
237 return 1.0f - (SpikeSize/SpikeTolerance);
239 // File_checked_for_headers