Initial Commit
This commit is contained in:
397
database/FileZillaFTP/source/ExternalIpCheck.cpp
Normal file
397
database/FileZillaFTP/source/ExternalIpCheck.cpp
Normal file
@@ -0,0 +1,397 @@
|
||||
// FileZilla Server - a Windows ftp server
|
||||
|
||||
// Copyright (C) 2002-2004 - Tim Kosse <tim.kosse@gmx.de>
|
||||
|
||||
// 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.
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "ExternalIpCheck.h"
|
||||
#include "ServerThread.h"
|
||||
#include "Options.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
// Konstruktion/Destruktion
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TIMERINTERVAL 30
|
||||
|
||||
CExternalIpCheck::CExternalIpCheck(CServerThread *pOwner)
|
||||
{
|
||||
ASSERT(pOwner);
|
||||
m_pOwner = pOwner;
|
||||
|
||||
m_bActive = FALSE;
|
||||
m_nRetryCount = 0;
|
||||
m_nTimerID = SetTimer(0, 0, TIMERINTERVAL * 1000, 0);
|
||||
m_bTriggerUpdateCalled = FALSE;
|
||||
m_nFailedConnections = 0;
|
||||
m_nElapsedSeconds = 0;
|
||||
|
||||
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
|
||||
return;
|
||||
|
||||
if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 2)
|
||||
Start();
|
||||
else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
|
||||
{
|
||||
CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
|
||||
SOCKADDR_IN sockAddr;
|
||||
memset(&sockAddr, 0, sizeof(sockAddr));
|
||||
|
||||
sockAddr.sin_family = AF_INET;
|
||||
#ifdef _UNICODE
|
||||
sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
|
||||
#else
|
||||
sockAddr.sin_addr.s_addr = inet_addr(hostname);
|
||||
#endif
|
||||
|
||||
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
LPHOSTENT lphost;
|
||||
#ifdef _UNICODE
|
||||
lphost = gethostbyname(ConvToLocal(hostname));
|
||||
#else
|
||||
lphost = gethostbyname(hostname);
|
||||
#endif
|
||||
if (lphost != NULL)
|
||||
|
||||
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
|
||||
else
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ip = inet_ntoa(sockAddr.sin_addr);
|
||||
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
#ifdef _UNICODE
|
||||
m_IP = ConvFromLocal(ip);
|
||||
#else
|
||||
m_IP = ip;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
CExternalIpCheck::~CExternalIpCheck()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void CExternalIpCheck::OnReceive(int nErrorCode)
|
||||
{
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
if (nErrorCode)
|
||||
{
|
||||
m_bActive = FALSE;
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
return;
|
||||
}
|
||||
char buffer[1000];
|
||||
int len = Receive(buffer, 999);
|
||||
|
||||
if (len == SOCKET_ERROR)
|
||||
{
|
||||
if (GetLastError() == WSAEWOULDBLOCK)
|
||||
return;
|
||||
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
buffer[len] = 0;
|
||||
char *p = strstr(buffer, "\r\n\r\n");
|
||||
if (!p)
|
||||
p = strstr(buffer, "\n\n");
|
||||
|
||||
if (!p)
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
while (*p && (*p == '\n' || *p == '\r'))
|
||||
p++;
|
||||
|
||||
if (!*p)
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
char * ip = p;
|
||||
while (*p && *p != '\n' && *p != '\r')
|
||||
p++;
|
||||
*p = 0;
|
||||
|
||||
SOCKADDR_IN sockAddr;
|
||||
memset(&sockAddr,0,sizeof(sockAddr));
|
||||
|
||||
sockAddr.sin_family = AF_INET;
|
||||
sockAddr.sin_addr.s_addr = inet_addr(ip);
|
||||
|
||||
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
LPHOSTENT lphost;
|
||||
lphost = gethostbyname(ip);
|
||||
if (lphost != NULL)
|
||||
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
|
||||
else
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ip = inet_ntoa(sockAddr.sin_addr);
|
||||
|
||||
if (!ip)
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
m_IP = ConvFromLocal(ip);
|
||||
#else
|
||||
m_IP = ip;
|
||||
#endif
|
||||
|
||||
m_nFailedConnections = 0;
|
||||
|
||||
Close();
|
||||
m_nRetryCount = 0;
|
||||
m_bActive = FALSE;
|
||||
}
|
||||
|
||||
void CExternalIpCheck::OnConnect(int nErrorCode)
|
||||
{
|
||||
if (!m_bActive)
|
||||
return;
|
||||
|
||||
if (nErrorCode)
|
||||
{
|
||||
m_bActive = FALSE;
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
CStdStringA address = "GET " + m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER) + " HTTP/1.0\r\nUser-Agent: FileZilla Server\r\n\r\n";
|
||||
const char *buffer = address;
|
||||
int len = strlen(buffer);
|
||||
if (Send(buffer, len) != len)
|
||||
{
|
||||
m_bActive = FALSE;
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
}
|
||||
|
||||
OnReceive(0);
|
||||
}
|
||||
|
||||
void CExternalIpCheck::OnTimer()
|
||||
{
|
||||
if (m_nElapsedSeconds <= 1000000)
|
||||
m_nElapsedSeconds += TIMERINTERVAL;
|
||||
|
||||
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
|
||||
{
|
||||
m_nRetryCount = 0;
|
||||
Close();
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
else if (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE) == 1)
|
||||
{
|
||||
m_nRetryCount = 0;
|
||||
Close();
|
||||
m_bActive = FALSE;
|
||||
|
||||
CStdString hostname = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIP);
|
||||
SOCKADDR_IN sockAddr;
|
||||
memset(&sockAddr,0,sizeof(sockAddr));
|
||||
|
||||
sockAddr.sin_family = AF_INET;
|
||||
#ifdef _UNICODE
|
||||
sockAddr.sin_addr.s_addr = inet_addr(ConvToLocal(hostname));
|
||||
#else
|
||||
sockAddr.sin_addr.s_addr = inet_addr(hostname);
|
||||
#endif
|
||||
|
||||
if (sockAddr.sin_addr.s_addr == INADDR_NONE)
|
||||
{
|
||||
LPHOSTENT lphost;
|
||||
#ifdef _UNICODE
|
||||
lphost = gethostbyname(ConvToLocal(hostname));
|
||||
#else
|
||||
lphost = gethostbyname(hostname);
|
||||
#endif
|
||||
if (lphost != NULL)
|
||||
sockAddr.sin_addr.s_addr = ((LPIN_ADDR)lphost->h_addr)->s_addr;
|
||||
else
|
||||
{
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_bActive = FALSE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char *ip = inet_ntoa(sockAddr.sin_addr);
|
||||
|
||||
if (!ip)
|
||||
return;
|
||||
|
||||
#ifdef _UNICODE
|
||||
m_IP = ConvFromLocal(ip);
|
||||
#else
|
||||
m_IP = ip;
|
||||
#endif
|
||||
m_nFailedConnections = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!m_bActive && m_nRetryCount)
|
||||
{
|
||||
if (m_nElapsedSeconds > 60 && m_nRetryCount < 5)
|
||||
{
|
||||
Start();
|
||||
return;
|
||||
}
|
||||
else if (m_nElapsedSeconds > 300 && m_nRetryCount < 10)
|
||||
{
|
||||
Start();
|
||||
return;
|
||||
}
|
||||
else if (m_nElapsedSeconds > 900 && m_nRetryCount < 20)
|
||||
{
|
||||
Start();
|
||||
return;
|
||||
}
|
||||
else if (m_nElapsedSeconds > 3600)
|
||||
{
|
||||
Start();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (m_bActive)
|
||||
{
|
||||
if (m_nElapsedSeconds > 30)
|
||||
{
|
||||
m_bActive = FALSE;
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
m_nElapsedSeconds = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_nElapsedSeconds > 300 && m_bTriggerUpdateCalled)
|
||||
Start();
|
||||
else if (m_nElapsedSeconds > 3600)
|
||||
Start();
|
||||
}
|
||||
}
|
||||
|
||||
void CExternalIpCheck::OnClose(int nErrorCode)
|
||||
{
|
||||
if (m_bActive)
|
||||
{
|
||||
m_bActive = FALSE;
|
||||
Close();
|
||||
m_nRetryCount++;
|
||||
}
|
||||
}
|
||||
|
||||
void CExternalIpCheck::Start()
|
||||
{
|
||||
if (m_bActive)
|
||||
return;
|
||||
|
||||
CStdString address = m_pOwner->m_pOptions->GetOption(OPTION_CUSTOMPASVIPSERVER);
|
||||
if (address.Left(7) == _T("http://"))
|
||||
address = address.Mid(7);
|
||||
int pos = address.Find('/');
|
||||
if (pos != -1)
|
||||
address = address.Left(pos);
|
||||
if (address == _T(""))
|
||||
return;
|
||||
|
||||
m_bTriggerUpdateCalled = FALSE;
|
||||
|
||||
m_nElapsedSeconds = 0;
|
||||
Create();
|
||||
|
||||
BOOL res = Connect(address, 80);
|
||||
if (res == SOCKET_ERROR && GetLastError() != WSAEWOULDBLOCK)
|
||||
m_nRetryCount++;
|
||||
else
|
||||
m_bActive = TRUE;
|
||||
}
|
||||
|
||||
void CExternalIpCheck::TriggerUpdate()
|
||||
{
|
||||
if (m_bActive)
|
||||
return;
|
||||
|
||||
m_bTriggerUpdateCalled = TRUE;
|
||||
if (m_nFailedConnections < 100000)
|
||||
m_nFailedConnections++;
|
||||
}
|
||||
|
||||
CStdString CExternalIpCheck::GetIP(const CStdString& localIP)
|
||||
{
|
||||
if (!m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
|
||||
return _T("");
|
||||
|
||||
CStdString ip;
|
||||
switch (m_pOwner->m_pOptions->GetOptionVal(OPTION_CUSTOMPASVIPTYPE))
|
||||
{
|
||||
case 0:
|
||||
return _T("");
|
||||
case 2:
|
||||
if (!m_bActive && !m_nRetryCount && localIP != _T(""))
|
||||
{
|
||||
if (localIP == m_IP)
|
||||
m_nElapsedSeconds = 0;
|
||||
}
|
||||
case 1:
|
||||
ip = m_IP;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return ip;
|
||||
}
|
||||
Reference in New Issue
Block a user